Jump to content

Search the Community

Showing results for tags 'module'.

  • Search By Tags

    Type tags separated by commas.
  • Search By Author

Content Type


Forums

  • Welcome to ProcessWire
    • News & Announcements
    • Showcase
    • Wishlist & Roadmap
  • Community Support
    • Getting Started
    • Tutorials
    • FAQs
    • General Support
    • API & Templates
    • Modules/Plugins
    • Themes and Profiles
    • Multi-Language Support
    • Security
    • Jobs
  • Off Topic
    • Pub
    • Dev Talk

Product Groups

  • Form Builder
  • ProFields
  • ProCache
  • ProMailer
  • Login Register Pro
  • ProDrafts
  • ListerPro
  • ProDevTools
  • Likes
  • Custom Development

Find results in...

Find results that contain...


Date Created

  • Start

    End


Last Updated

  • Start

    End


Filter by number of...

Joined

  • Start

    End


Group


AIM


MSN


Website URL


ICQ


Yahoo


Jabber


Skype


Location


Interests

  1. Floating Page Save adds a floating copy of the native Save control to ProcessWire’s page editor so it stays within reach while you scroll long pages. GitHub: https://github.com/dlzi/FloatingPageSave
  2. Hi everyone, A visual menu builder for ProcessWire has been on my to-do list for a long time, and it’s finally ready. Meet NativeMenu: you build every kind of menu visually, with drag & drop and no code. Simple dropdowns, mega menus and a logo in the middle are all possible. What it does Visual editor. The menu bar is edited as it looks. Drag elements or pages from the tree onto it, click an item to edit it, double-click to rename. Undo/redo, drafts, versions and a live preview are included. Mega menus. Columns with a 12-unit grid. Blocks: links, headings, text, images, latest articles, buttons, search and HTML. Mobile. Drawer (left/right), fullscreen or push-down menu. Submenus open as an accordion or as slide-in panels. Each mega menu has its own mobile layout. Design without CSS. Style presets, colors, background, gradient or image, border, shadow and font. “Match my website” reads colors and fonts from your template. Bootstrap 5, UIkit 3 and plain markup are supported, and every class can be overridden. Effects. Dropdown animations (fade, slide, grow, unfold, reveal), hover effects including a sliding indicator, a sticky / shrinking / hide-on-scroll header and an animated menu button. Smart import. Paste the menu HTML of any template, or give a URL. Links are matched to your real pages, and the original markup can be kept. An optional AI assistant can build a menu from a description or match the remaining links. One menu, many outputs. The same menu can also be rendered as footer columns, breadcrumbs (with JSON-LD), an HTML sitemap, an “In this section” sidebar, or as raw data for custom markup. Multilanguage. Labels and URLs per language, page items follow the page title and URL in each language, and there is a language switcher with hreflang. SEO / GEO. Clean <nav> markup and schema.org SiteNavigationElement. rel attributes per item. /llms.txt generated from your menus, per language. Check tab. Flags broken links and pages that were deleted, unpublished or hidden. Flags missing translations, alt texts and low color contrast (WCAG). External links are checked daily. More: show items only on certain pages or templates, scheduled items (from / until), visibility by role, anonymous click statistics (with NativeAnalytics integration), a library of reusable blocks, and a one-click offer to add new pages to the menu. AI assistant (optional) NativeMenu includes an optional AI assistant. It works with Anthropic (Claude) or any OpenAI-compatible API, including Azure, Mistral or a local server. Enter your API key in the module settings to switch it on. Build a menu from a description. In the import dialog, choose Describe (AI) and write what you want. For example: "Main menu with Home, a mega menu 'Services' with one column per category and an image, About us with its subpages, Blog, and a 'Contact' button on the right." The AI only uses pages that exist on your site, so every link works. Match links when importing a template. After a template import, links that could not be matched get an Ask AI to match button. The AI finds the right pages even across languages (e.g. "O nas" → "About us"). Every match it finds is marked "to check". You always review first. Proposals appear in the same review table as a normal import, and nothing is saved until you confirm. Private. Only page IDs, paths and titles are sent to the provider, never page content or user data. Requests are limited to 30 per user per hour. Extendable. NativeMenuAI::request is hookable, so you can connect any other provider. Usage php <?= $modules->get('NativeMenu')->render('main-menu') ?> <?= $modules->get('NativeMenu')->renderColumns('main-menu') ?> // footer <?= $modules->get('NativeMenu')->renderBreadcrumbs('main-menu') ?> CSS and JS are added automatically, only on pages that show a menu. Menus are cached per language and role, and the cache is cleared when a page in the menu changes. Requirements: ProcessWire 3.0.200+, PHP 7.4+ (tested on 8.3). It works with the Uikit (incl. Konkat light/dark), Reno and Default admin themes. Install: copy the folder to /site/modules/NativeMenu/, install the module and open Setup → Menus. Feedback and ideas are very welcome! Download: NativeMenu-1.0.6.zip Enjoy R
  3. This module extends WireMail base class, integrating the PHPMailer mailing library into ProcessWire. Module Directory - Githup repo
  4. Hi everyone, I’m happy to share NativeAnalytics, a native first-party analytics module for ProcessWire. The module is now available in the ProcessWire modules directory: https://processwire.com/modules/native-analytics/ NativeAnalytics provides a useful analytics dashboard directly inside the ProcessWire admin, without relying on external analytics platforms, third-party scripts or external APIs. All analytics data is stored locally in your ProcessWire installation, which makes it a good fit for projects where you want a simpler, more self-contained analytics solution. The module currently tracks and displays: page views unique visitors sessions current visitors top pages referrers devices and browsers 404 hits engagement events such as form submits, downloads, tel/mail clicks, outbound clicks and custom CTA events It also includes: charts and trend views comparison between periods custom date range filtering page-level analytics inside the page edit screen optional monthly email reports optional PDF report attachments exports to CSV, PDF and DOCX helper examples and a small snippet generator for custom event tracking New in the latest version: Goals and conversion tracking event-based goals, for example form submits, CTA clicks, downloads or tel/mail clicks page/path-based goals, for example thank-you pages or booking confirmation pages conversion rate reporting based on sessions and unique visitors a dedicated Goals dashboard with goal cards, goal trends and goal overview easier goal setup with helper text, quick presets and suggestions from already tracked events and pages daily aggregate tables for events and goals raw event retention setting additional database indexes and cleanup helpers for larger datasets There are also several privacy and consent-related options: optional cookie-less visitor/session mode consent-based tracking helper functions for custom consent integrations optional PrivacyWire localStorage consent helper support cleaner behaviour when global tracking is disabled The reason I built this module was that I wanted something that feels natural inside ProcessWire itself, instead of embedding another analytics service into the admin. For many sites, it can be useful to have core traffic, engagement and conversion data available right where content is managed. Goal tracking was added because several users asked for a simple way to measure important actions without having to fight with external analytics tools. For example, you can now create a goal for a contact form submit, a CTA button click, a file download or a visit to a thank-you page, and then see conversions and conversion rates directly in the ProcessWire admin. A small note about very large datasets: NativeAnalytics includes retention settings, daily aggregate tables and cleanup tools, and the latest version improves this further for events and goals. For very high-traffic sites, I still recommend using sensible raw data retention and keeping long-term reporting based on aggregated data. I do not want to overclaim without real long-term benchmarks on extremely large datasets, so feedback from larger installations is very welcome. ! If you tested one of the earlier development versions named PW Native Analytics, I recommend uninstalling that old test version first and installing NativeAnalytics as a fresh module, because the module name and structure changed during development. Multi-site analytics is not included yet, but it is something I am looking into. It would need proper per-site separation in the stored analytics data, so I want to approach that carefully rather than adding a quick workaround. Feedback, bug reports and suggestions are very welcome. Get it here: https://processwire.com/modules/native-analytics/ Enjoy! If you find NativeAnalytics useful and would like to support further development, maintenance and testing, a small donation is always appreciated. The module will remain free, but support helps me spend more time improving it and adding new features. DONATE
  5. Hi all, You know the moment: you're browsing your own site, you spot a typo in a title, an event that already happened, a date that's wrong. And you sigh, because now it's admin → find the page → edit → scroll → save → go back. Five screens for one word. So I built Native Command — a command palette for ProcessWire, like Spotlight/Raycast or the VS Code palette. Press Alt+K (⌥+K on Mac) on any page of your site, front-end or admin, type a couple of letters, hit Enter. Done. What can it do? Things with the page you're looking at: set any simple field (text, number, price, date, checkbox, options, page reference — yes, next friday 19:30 works), publish/unpublish, hide, rename, duplicate, add a child page, move it, trash it. Undo. Everything. Every change shows a little toast with an Undo button. Your editors will love you. You'll sleep better. Bulk actions with selectors. "Unpublish all events that already happened": bulk unpublish → template=event, event_date<today → untick the one you want to keep → Enter. You get a summary of what was done and skipped (and why) — and one Undo for the whole batch. "Wait, who uses this page?" Page info shows who created/changed it, URLs in all languages, and which pages reference or link to it. Trash and Move warn you about it automatically, before you break something. Search & jump to pages (title, ID, template or a selector), admin screens, templates, fields, modules and users. Every page shows its template and ID — click the ID to copy it. And a few extras: system info and latest errors right in the palette, clear caches, refresh modules, add a field to a template, your own no-code shortcuts in the settings (New event | new /events/ event | editor), pins, dark mode, and ? for built-in help. Is it safe to give to editors? Yes — that was the whole point. Every command, page and field is checked against the user's permissions on the server, every time. Commands use CSRF, risky ones ask first, rich-text fields are never touched, user selectors can't sneak past access control, and changes can be logged. No tables, fields or templates are created — uninstall and it's gone. For developers Add your own commands from any module or ready.php — with arguments, page pickers, confirmations, results in the palette and undo: php $wire->addHookAfter('NativeCommand::registerCommands', function(HookEvent $e) { $e->object->addCommand('orders.open', [ 'title' => 'Open orders', 'mutates' => false, 'handler' => function() { return ['message' => wire('pages')->count('template=order, paid=0') . ' open orders']; }, ]); }); Extra screens: Download Works on any site, any profile, no dependencies. ProcessWire 3.0.200+, PHP 7.4+. Download: NativeCommand.zip Install, press Alt/⌥+K, type ?. If you run into any problems or bugs, please let me know and if it saves you even one trip through the page tree, I'll call it a win. 🙂 Cheers R
  6. Hi all, I needed a real forum on a ProcessWire site. This is it: Native Forum, fully built, and it installs on an existing site without touching what’s already there. The forum part Structure: groups, categories, topics and replies, with pinned and locked topics, tags, search and a member list. Posting: quotes, “in reply to”, likes/votes, a copy link and share cards for every post. Members: private messages with a “you’ve got mail” popup, followed topics with e-mail notifications, and a “Followed topics” tab that shows what’s new. Profiles: avatar, signature and ranks (manual or by post count). Editor: CKEditor with drag & drop uploads, resizable images and file attachments. Keeping it clean Anti-spam: honeypot, JS challenge, link limits for newcomers, disposable-email and MX checks, StopForumSpam and optional Cloudflare Turnstile. Bots get bored, humans don’t notice. Moderation: a report button and a dashboard with Hide/Lock/Delete in one click. You can edit every topic and reply right from the admin. SEO, GEO & speed SEO: clean meta tags, JSON-LD, RSS and a sitemap. Share cards: Open Graph cards with the right picture for each reply. GEO (AI search): Markdown versions of topics and an /llms.txt file. Speed: fast, with batched queries, and ProCache-friendly. Fits your site, not the other way round It renders inside your own _main.php (Markup Regions or $content) or as a standalone page. One switch hides your site’s page loader on forum pages. You can add your own header, footer, <head> markup, or anything before or after the forum. Looks Six ready-made presets: Obsidian, Light, Dark, Auto, Monochrome and Custom. A Simple or Bootstrap 5 theme, and a Classic or Compact layout. Design Studio, if you want to tweak every colour and size yourself. Pick a preset, and your forum looks finished before your coffee gets cold. ☕ Themes: ... Admin goodies Dashboard: reports, groups and categories (drag & drop), topics, messages and members. Settings: neatly arranged. It also works in Konkat dark mode and on phones. Optional demo content: pinned forum rules and a few sample topics, removable in one click. Export / Import: move the whole forum to another site as one .zip: settings, posts, files, members, and even passwords (encrypted hashes, so members just log in as before). Clean uninstall: it removes everything it created, with a big red warning first. Install: copy the module to /site/modules/NativeForum/, run Modules > Refresh, and install Native Forum. The admin installs itself. Then open /forum/. That’s it. Download: NativeForum.zip Feedback, bug reports and ideas are very welcome. And if you build a community with it, show it off! 🙂 Cheers 😉 R
  7. Hi everyone, I'd like to share Cookie, a consent management module I've been building — a consent banner, preferences window, server-side auto-blocking of trackers, and an interactive visual builder for styling the whole thing without touching CSS. GitHub: https://github.com/mxmsmnv/Cookie Demo (Design Studio): https://drive.google.com/file/d/1u5nSmBogZJd8FF5vVZ_R2CABkSAZvXl2/view Why Most consent solutions I looked at made you choose: either you get compliance (trackers actually blocked before consent) or you get design control (colors, layout, icon placement) — rarely both without editing CSS/JS by hand. Cookie tries to give you both. What it does Consent-first by default. Known trackers and embeds (GTM, Google Analytics, Yandex Metrika, Meta Pixel, Hotjar, Clarity, DoubleClick, TikTok, YouTube, Vimeo, Google Maps and more) are neutralized server-side, in the rendered page, before it reaches the browser. Two consent models: opt-in (GDPR/ePrivacy, UK GDPR/PECR, LGPD, Law 25, POPIA, KVKK) and opt-out (CCPA/CPRA and other US state laws), plus Global Privacy Control support, and a geo mode that picks the model automatically by visitor country. Category-based blocking of scripts, iframes, images and video, with placeholders and multi-category requirements. A visual builder (Setup > Cookie — "Design Studio"): live-preview layout, colors, fonts, radius, shadows, spacing. 50 color presets, 25 icon-color presets, 18 dark-theme presets. A floating settings icon with 7 built-in choices, adjustable shape/size/position/color/shadow, including a transparent icon-only mode. A dark theme with its own live-edited color set. A services catalog + cookie policy generator. Google Consent Mode v2, consent expiry/versioning, JS API, CustomEvents. Optional consent log with CSV export and a small statistics dashboard. Everything is hookable, and it's multi-language out of the box with per-language text targeting. Basic usage <script type="text/plain" data-consent="statistics" src="https://example.com/analytics.js"></script> $wire->addHookAfter('Cookie::allowCategory', function($e) { if ($e->arguments(0) === 'marketing') $e->return = false; }); Installation Copy to /site/modules/, install, configure texts/categories in module settings, design the widget in Setup > Cookie. Requires ProcessWire 3.0.244+ and PHP 8.2+. MPL-2.0 licensed. Full docs and hooks reference: README. This is the 1.0.0 release — feedback and bug reports welcome! GitHub: https://github.com/mxmsmnv/Cookie Demo (Design Studio): https://drive.google.com/file/d/1u5nSmBogZJd8FF5vVZ_R2CABkSAZvXl2/view
  8. Hi all, I'd like to introduce LePdf, a small ProcessWire module that wraps mPDF: you give it HTML, it gives you a PDF. You can show it in the browser, send it as a download, save it to disk, or get it as a string. The mPDF instance stays directly accessible, so nothing is hidden from you. Why another PDF module? I use RockPdf in a few projects, and its development has been discontinued. I wanted something small that I can maintain myself, runs on plain shared hosting, and covers what I actually need: output, download, save. LePdf is an independent implementation. The basic idea (a thin wrapper around mPDF) is inspired by RockPdf. I contacted @bernhard beforehand, and he replied that he has no problem with it and is happy about it. ❤️ LePdf is not a drop-in replacement. There is no backwards compatibility with the RockPdf API. Features write(), css(), renderTemplate(), show(), download(), save(), output() Header, footer, title, author (set globally in the module config or per document) Custom fonts and icon fonts (e.g. FontAwesome) Direct access to the mPDF instance via $pdf->mpdf mPDF is bundled, so no Composer is needed (useful on shared hosting) Module configuration page with an explanation and example for every field Config page translatable with ProcessWire's language system; CSV files for DE, FR, ES, PT, IT, NL are included Quick start $pdf = $modules->get('LePdf'); // every get() returns a new, empty PDF $pdf->write('<h1>Hello</h1><p>This is a PDF.</p>'); $pdf->show('hello.pdf'); // show in the browser and end the script Example: attendance list with a signature column <?php namespace ProcessWire; // check access before anything is generated if(!$user->isLoggedin() || !$user->hasRole('editor')) throw new Wire404Exception(); $event = $pages->get((int) $input->get->id); $rows = ''; foreach($event->participants->sort('name') as $u) { $rows .= '<tr><td>' . $sanitizer->entities($u->name) . '</td><td></td><td></td></tr>'; } $pdf = $modules->get('LePdf'); $pdf->title("Attendance {$event->title}"); $pdf->css('td, th { border: 1px solid #000; padding: 4mm; } th { background: #eee; }'); $pdf->write('<h2>' . $sanitizer->entities($event->title) . "</h2> <table width='100%' style='border-collapse: collapse'> <tr><th>Name</th><th width='15%'>Present</th><th width='35%'>Signature</th></tr> $rows </table>"); $pdf->show('attendance.pdf'); The admin configuration page Requirements PHP 7.4 or newer (bundled mPDF 8.3 supports up to PHP 8.5) ProcessWire 3.0 or newer PHP extensions mbstring and gd; zlib recommended Installation Copy the folder to site/modules/LePdf/, then Modules > Refresh > install LePdf. Details are in the README. Status Version 0.1.0, early. I tested it manually on PHP 8.5 on shared hosting; the automated tests (which run without ProcessWire) run on PHP 8.3. Real-world testing on other setups is exactly what I'm missing. Notes LePdf does not check permissions and does not escape HTML. Access control and escaping belong in your template (see the README). The translations were created with AI assistance and have not been reviewed by native speakers. Corrections are welcome. Feedback I'd be glad about bug reports, test results on other hosting setups, corrections to the translations, and ideas for what should come next. I'm deliberately keeping version 1 small. License LePdf is MIT. The bundled mPDF is GPL-2.0-only (see lib/THIRD-PARTY.md in the repo). GitHub repository
      • 12
      • Like
  9. Automatically generate captions and transcripts for audio and video files using the Speechmatics API. You can find the module on Github, or in the ProcessWire modules directory (submission pending). A ProcessWire CMS module that watches selected file fields, submits supported media files to Speechmatics for transcription, and automatically saves the resulting WebVTT .vtt caption files back into ProcessWire. Once configured, editors upload audio or video files as usual. The module handles the transcription workflow in the background and stores the returned caption files in a set field, ready for use. Why use this module? Automatic caption generation for uploaded media Supports both audio and video files Bring your own Speechmatics API key Stores standard WebVTT (.vtt) caption files Minimal editor involvement once configured Allows for caption files to be tagged as a 'draft' Improves accessibility and compliance for your media Integrates directly into existing ProcessWire content workflows Requirements PHP 7.3+ ProcessWire 3.0.244+ FFmpeg installed on the server A Speechmatics account and API key An allowed connection between your web server and the Speechmatics API endpoint (both ways, to send the file and recieve a callback) How it works An editor uploads an audio or video file to a configured file field The module detects the new media file on page save The file is submitted to the Speechmatics transcription API Speechmatics processes the media and generates captions A WebVTT (.vtt) caption file is returned via a webhook The caption file is automatically saved into the configured ProcessWire file field The captions are available, optionally tagged to indiciate they have not been reviewed yet Configuration URL to the Speechmatics API Allows you to change the URL used for the Speechmatics API, usually the default is fine. Speechmatics API Key Enter your Speechmatics API key. The module will validate the key when the configuration is saved and display an error if it cannot authenticate with the Speechmatics API. Callback URL Specify the URL in which you would like to recieve the callback from Speechmatics once a job is complete and ready to import. On saving, the route will be tested to ensure it does not conflict with an existing page. Path to FFmpeg The path to run the FFmpeg CLI tool. This is used to strip audio from video files to save bandwidth communicating with the API. Model Allows you to choose which Speechmatics model to use, between 'Standard' and 'Enhanced'. Language The language that content is in. See a full list of ISO language codes. Only 2 letter codes are supported, use en instead of en-US for example. Output Locale Language locale to be used, normally specified as an ISO language code. See a full list of ISO language codes. Full length language codes are supported, like en-US. Content File Field Select which field stores the audio/video file to be sent to Speechmatics for transcription. Only files uploaded to this field will be processed. Caption Output Field Select the file field that should receive generated .vtt caption files. The module will automatically save caption files here once transcription has completed. Caption File Field Select which field to store the .vtt caption file from Speechmatics. Tags to skip Allows you to choose which files are skipped from being transcribed. Can be helpful to skip processing files that are have no dialog, or have another reason to be skipped. Tag to give files that have no dialog Choose what tag is given to media files that have no transcribable dialog detected. Handy for ensuring they are not sent to Speechmatics for repeat processing needlessly. Tag to give caption files that have been added Choose a tag to give any captions files that have been added. handy for tracking drafts that need a review before being used. Phonetic "sounds like" suggestions Allow a list of custom words to be added for each transcription job. This helps when a specific word is not recognised during transcription. Format as a comma seperated list, where the first phrase/word is the correct spelling and the following words/phrases are what it may sound like. Every new line is a new word. Example: gnocchi,nyohki,nokey,nochi The first word is the intended word, following are phonetic phrases the word may sound like. Using this module You can hook the SpeechmaticsTranscription::saveCaptionsToPage to trigger actions when captions are being returned and saved to a page. This can be useful for triggering notifications when captions are ready, such as an email using WireMail. /** * Example of a notification to the author whenever * captions have been added to a page */ wire()->addHookAfter('SpeechmaticsTranscription::saveCaptionsToPage', function (HookEvent $e) { $page = $e->arguments(0); if ($page->id === 0) { return; // null page, cancel notification } // Email body $emailBody = <<<HTML <p>New automated captions have been uploaded for the <em>$page->title</em> page on the <a href='$page->httpUrl'>$page->title</a> page.</p> <p>Edit: <a href='{$page->editUrl(true)}'>$page->httpUrl</a></p> <p>Please review the draft caption file, make any edits necessary and remove the ‘draft’ tag when they are ready to use.</p> HTML; // Send email using WireMail wire('mail') ->to('firstname.lastname@example.com') ->from('noreply@example.com') ->subject("A page has new captions to review") ->bodyHTML($emailBody) ->send(); }); Let us know how you go using this module! We've found it rather useful.
  10. I missed the XML sitemap generator that I used in a previous CMS so I built my own module to achieve the same functionality. This module outputs an XML sitemap of your site that is readable by Google Webmaster Tools etc. I've generally found that it reduces the time it takes for new sites and pages to be listed in search engines using one in combination with Webmaster Tools etc (since you're specifically telling the service that a new site/new pages exist) so thought I may as well create a module for it. The module ignores any hidden pages and their children, assuming that since you don't want these to be visible on the site then you don't want them to be found via search engines either. It also adds a field called sitemap_ignore that you can add to your templates and exclude specific pages on a per-page basis. Again, this assumes that you wish to ignore that page's children as well. The sitemap is accessible at yoursite.com/sitemap.xml - the module checks to see whether this URL has been called and outputs the sitemap, then does a hard exit before PW gets a chance to output a 404 page. If there's a more elegant way of doing this I'll happily change the code to suit. Feedback and suggestions welcome On a slightly different note, I wanted to call the file XMLSitemap originally so as to be clearer about what it does in the filename, but if you have a module that begins with more than one uppercase letter then a warning containing only the module name is displayed on the Modules page, so I changed it to Sitemap instead which is fine as the description still says what it does. File can be downloaded via GitHub here: https://github.com/N.../zipball/master
  11. Cacheable Placeholders This module allows you to have pieces of dynamic content inside cached output. This aims to solve the common problem of having a mostly cacheable site, but with pieces of dynamic output here and there. Consider this simple example, where you want to output a custom greeting to the current user: <h1>Good morning, <?= ucfirst($user->name) ?></h1> This snippet means you can't use the template cache (at least for logged-in users), because each user has a different name. Even if 99% of your output is static, you can only cache the pieces that you know won't include this personal greeting. A more common example would be CSRF tokens for HTML forms - those need to be unique by definition, so you can't cache the form wholesale. This module solves this problem by introducing cacheable placeholders - small placeholder tokens that get replaced during every request. The replacement is done inside a Page::render hook so it runs during every request, even if the response is served from the template cache. So you can use something like this: <h1>Good morning, {{{greeting}}}</h1> Replacement tokens are defined with a callback function that produces the appropriate output and added to the module through a simple hook: // site/ready.php wire()->addHookAfter('CachePlaceholders::getTokens', function (HookEvent $e) { $tokens = $e->return; $tokens['greeting'] = [ 'callback' => function (array $tokenData) { return ucfirst(wire('user')->name); } ]; $e->return = $tokens; }); Tokens can also include parameters that are parsed and passed to the callback function. There are more fully annotated examples and step-by-step instructions in the README on Github! Features A simple and fast token parser that calls the appropriate callback and runs automatically. Tokens may include multiple named or positional parameters, as well as multi-value parameters. A manual mode that allows you to replace tokens in custom pieces of cached content (useful if you're using the $cache API). Some built-in tokens for common use-cases: CSRF-Tokens, replacing values from superglobals and producing random hexadecimal strings. The token format is completely customizable, all delimiters can be changed to avoid collisions with existing tag parsers or template languages. Links Github Repository & documentation Module directory If you are interested in learning more, the README is very extensive, with more usage examples, code samples and usage instructions!
  12. ProcessFileRenamer is a small ProcessWire admin Process module for safely renaming uploaded asset basenames. GitHub: https://github.com/dlzi/ProcessFileRenamer
      • 6
      • Like
  13. Here is my first processwire module (beta). https://github.com/theo222/ImagePickerField A lot of "first times". First time Github, Markdown and of course PW Modules. So be gentle please. I hope it works.
  14. **General** ProcessEndLinkageEditorial is a polished, non-technical editorial interface for ProcessWire that runs completely separate from the PW admin. Editors log in through their own front end and manage only the content types a developer has explicitly exposed — no templates, fields, or admin UI ever visible to them. Highlights: - Visual menu builder and dashboard - TinyMCE, repeater fields with an accordion UI - Transactional saving with automatic rollback (on validation *and* write failures) - Fine-grained per-role/per-template create/edit permissions - Audit log - Hardened login: rate limiting that only counts real failed attempts, session rotation, idle timeout - Optional TOTP 2FA, built entirely on PW's own core `Tfa` class (no custom TOTP code — requires a separately installed Tfa module such as TfaTotp) **How to use** Install the module, then go to Setup → Redaktion to configure three tabs: - *Content & Navigation* — which templates are exposed, and the menu structure - *Design & Branding* — company name, logo, theme colors, and a freely editable/removable developer credit (useful if another agency deploys this for their own clients) - *Access & System* — role-to-template permission mapping, demo login, URL path, session timeout, optional 2FA enforcement Editors then log in at the configured path (default `/editorial/`) with their normal PW user account and the `editorial-access` permission. **Installation** Standard module install. After install, verify the `editorial-access` permission and `editorial` role exist (the module creates them, but check under Access if the install was interrupted). No build step — plain PHP 8 / ProcessWire 3.x. **Screenshots** [Dashboard] [Setup menu builder] **Links** GitHub: https://github.com/eversthomas/ProcessEndLinkageEditorial Modules directory: [wird ergänzt, sobald freigeschaltet]
  15. Hello all, sharing my new module FieldtypeImageReference. It provides a configurable input field for choosing any type of image from selectable sources. Sources can be: a predefined folder in site/templates/ and/or a page (and optionally its children) and/or the page being edited and/or any page on the site CAUTION: this module is under development and not quite yet in a production-ready state. So please test it carefully. UPDATE: the new version v2.0.0 introduces a breaking change due to renaming the module. If you have an older version already installed, you need to uninstall it and install the latest master version. Module and full description can be found on github https://github.com/gebeer/FieldtypeImageReference Install from URL: https://github.com/gebeer/FieldtypeImageReference/archive/master.zip Read on for features and use cases. Features Images can be loaded from a folder inside site/templates/ or site/assets Images in that folder can be uploaded and deleted from within the inputfield Images can be loaded from other pages defined in the field settings Images can be organized into categories. Child pages of the main 'image source page' serve as categories mages can be loaded from any page on the site From the API side, images can be manipulated like native ProcessWire images (resizing, cropping etc.), even the images from a folder Image thumbnails are loaded into inputfield by ajax on demand Source images on other pages can be edited from within this field. Markup of SVG images can be rendered inline with `echo $image->svgcontent` Image names are fully searchable through the API $pages->find('fieldname.filename=xyz.png'); $pages->find('fieldname.filename%=xy.png'); Accidental image deletion is prevented. When you want to delete an image from one of the pages that hold your site-wide images, the module searches all pages that use that image. If any page contains a reference to the image you are trying to delete, deletion will be prevented. You will get an error message with links to help you edit those pages and remove references there before you can finally delete the image. This field type can be used with marcrura's Settings Factory module to store images on settings pages, which was not possible with other image field types When to use ? If you want to let editors choose an image from a set of images that is being used site-wide. Ideal for images that are being re-used across the site (e.g. icons, but not limited to that). Other than the native ProcessWire images field, the images here are not stored per page. Only references to images that live on other pages or inside a folder are stored. This has several advantages: one central place to organize images when images change, you only have to update them in one place. All references will be updated, too. (Provided the name of the image that has changed stays the same) Installation and setup instructions can be found on github. Here's how the input field looks like in the page editor: If you like to give it a try, I'm happy to hear your comments or suggestions for improvement. Install from URL: https://github.com/gebeer/FieldtypeImageReference/archive/master.zip Eventually this will go in the module directory, too. But it needs some more testing before I submit it. So I'd really appreciate your assistance. Thanks to all who contributed their feedback and suggestions which made this module what it is now.
  16. This is a Leaflet version of Ryans Google Maps marker module. @Github
  17. This is my first module. It is primitive, like my neighbor who loves to fire up his new Makita breaker hammer after 21:30h. Please, feel free to do whatever you want. I don't promise I will add better functionality but maybe... If you do, please ping and send me back. Thanks! It loads every page on the backend. It calculates the text width in two fields you choose on the configuration page.. If there are any updates, I will post them here. Happy ProcessWiring! PS: These measurements are specifically for desktop and Google's SERP (Search Engine Results Page). UPDATE on 15 May 2024: Google started to calculate (truncate) the meta title for 20px Arial yesterday. The Module has been updated. Here is the link to download/install the latest version: https://processwire.com/modules/seo-text-width/ EDIT: The version 0.0.5. Added two dropdown fields on the configuration page of the module. PROVE IMAGE: You can check the meta title, which was measured with 18px Arial and it was less than 512 pixels.
  18. PageMjmlToHtml Github: https://github.com/eprcstudio/PageMjmlToHtml Modules directory: https://processwire.com/modules/page-mjml-to-html/ A module allowing you to write your Processwire template using MJML and get a converted HTML output using MJML API. About Created by Mailjet, MJML is a markup language making it a breeze to create newsletters displayed consistently across all email clients. Write your template using MJML combined with Processwire’s API and this module will automatically convert your code into a working newsletter thanks to their free-to-use Rest API. Prerequisite For this module to work you will need to get an API key and paste it in the module’s configuration. Usage Once your credentials are validated, select the template(s) in which you’re using the MJML syntax, save and go visualize your pages to see if everything’s good. You will either get error/warning messages or your email properly formatted and ready-to-go. From there you can copy/paste the raw generated code in an external mailing service or distribute your newsletter using ProMailer. You can also transpile any arbitrary MJML code by instanciating the module and using its transpile() method: $mjml = "<mjml></mjml>"; /** @var PageMjmlToHtml $pmh */ $pmh = $modules->get("PageMjmlToHtml"); $result = $pmh->transpile($mjml); if($result->code === 200 && empty($result->errors)) { echo $result->html; } You can read more about the function in its attached PHPDoc comment. Please note the options will default to the module’s one. And as a bonus the method is also hookable: $wire->addHookBefore("PageMjmlToHtml::transpile", function(HookEvent $event) { $mjml = $event->arguments(0); /** @var Page $page */ $page = $event->arguments(1); $options = $event->arguments(2); if(!$page->id || $page->template != "specific-template") return; $options["relativeLinksParams"] = "utm_campaign=new-campaign-title"; $event->arguments(2, $options); }); Options The MJML output is cached to avoid repetitive API calls Not cached if there are errors/warnings Cleared if the page is saved Cleared if the template file has been modified A simple (dumb?) code viewer highlights lines with errors/warnings A button is added to quickly copy the raw code of the generated newsletter Not added if the page is rendered outside of a PageView Only visible to users with the page’s edit permission A shortcut is also added under “View” in the edit page to open the raw code in a new tab Multi-languages support Notes The code viewer is only shown to superusers. If there’s an error the page will display: Only its title for guests Its title and a message inviting to contact the administrator for editors If you are using the markup regions output strategy, it might be best to not append files to preserve your MJML markup before calling the MJML API. This option is available in the module’s settings. If your layout looks weird somehow, try disabling the minification in the options.
  19. Hi everyone, I am releasing Tickets, a ProcessWire module for private customer-support conversations, staff workflows and reusable support forms. The practical problem it solves is simple: support requests often begin in a generic inbox, lose their context, and become difficult for both the customer and the team to follow. Tickets keeps that workflow inside ProcessWire, next to the accounts and content it supports, without turning private conversations into public comments. How it is used on LQRS Tickets is running on LQRS.com and its development site. The public flow shows the main value of the module: A visitor can open a private request without creating an account. The guest receives a secure access link and continues the same conversation from the website. Messages, status changes and private attachments stay together instead of being scattered across email threads. Signed-in members get a single view of their active and resolved requests. The support team works from a ProcessWire queue with assignment, priorities, internal notes, SLA state and reporting. After resolution, the customer can rate the support experience or reopen the request. For LQRS this means the Help Center remains the first place for immediate answers, while issues that require account context, a data correction, moderation review or a private file move into a trackable support workflow. What Tickets includes Authenticated and guest tickets with threaded replies. Hashed guest-access links and private attachment delivery. Statuses, priorities, assignment, routing rules, SLA targets and bulk actions. Staff-only notes, related tickets, merging and an audit trail. Reusable intake forms with validation, previews and shortcode embeds. One-way import of FormBuilder definitions into independent Tickets form drafts. Editable transactional mail templates through a selectable ProcessWire WireMail provider. Reports, CSV export, ratings, automation and retention tools. Bundled admin translations for Dutch, French, German, Italian and Spanish. Site-owned frontend Tickets owns the support domain, storage, permissions and public API. It deliberately does not overwrite the site's design. The consuming site supplies site/templates/tickets.php, controls routing below the configured support page, and composes the module output into its own frontend. A reusable form can be embedded in otherwise cacheable content: <?php namespace ProcessWire; if($modules->isInstalled('Tickets')) { /** @var Tickets $tickets */ $tickets = $modules->get('Tickets'); echo $tickets->renderFormEmbed('report-incorrect-data'); } Editors can also use: [[tickets-form:report-incorrect-data]] The API covers ticket creation, account and guest access, replies, ratings, attachments, custom forms, staff operations, reports and optional integrations. Exact signatures and authorization boundaries are documented in API.md. Privacy and operational boundaries Customer conversations and files are private; internal notes never belong in customer output. Browser writes require ProcessWire CSRF validation. Guest tokens are stored as hashes, and support routes should use private/no-store/noindex responses. Attachment access is authorized before a private filesystem path is used. Transactional delivery, inbound email, AI assistance and retention are all explicit opt-ins. Uninstall keeps ticket data by default rather than silently deleting customer records. Optional integrations Core ticketing works without additional modules. Optional integrations include WireMail providers for delivery, Resend for authenticated inbound replies, Mailbox for bounded email ingestion and SMTP reply threading, and staff-requested Squad drafts grounded by Atlas or Knowledge Base. AI drafts never send automatically. Requirements and installation ProcessWire 3.0.200 or newer. PHP 8.1 or newer. Download or clone Tickets into /site/modules/Tickets/. Refresh modules and install Tickets. Review the public path, legal links, recipients, attachment rules and optional integrations. Add the site-owned site/templates/tickets.php frontend. Grant tickets-manage and tickets-admin only to the appropriate support roles. Enable transactional delivery only after the selected mail provider has been tested. Links GitHub repository Download ZIP README Integration documentation Public API reference Live support portal on LQRS Issues and feedback I would especially appreciate feedback on the public route contract, permission boundaries and support workflows used on real ProcessWire sites.
  20. Hey folks, fun fact: this module was already featured in this week’s ProcessWire Weekly – even before we managed to post it here in the forum. So, here we are, finally giving it a proper introduction! 😅 TL;DR: This module connects Stripe Payment Links with ProcessWire and provides a simple checkout integration for sites that don’t need a full shop. 🎯 ✅ Drop a Stripe buy button anywhere ✅ Redirect back to PW thank-you or delivery pages ✅ Buyers get accounts, purchases are logged, access is granted ✅ Access mails are sent automatically ✴️ New in v 1.0.7: Sync existing purchases and buyers from Stripe to PW with test/write option ✴️ New in v 1.0.8: Full Stripe subscription support with real-time webhook updates (cancel, pause, resume, renew) and smarter access control logic ✴️ New in v 1.0.10: Notify existing buyers and update purchases when products gain gated content. ✴️ New in v 1.0.11: More flexible Access mails ✴️ New in v 1.0.14: Create and send "Magic Links" (access links) to customers for products they've already purchased. ✴️ New in v 1.0.23: Give Free Product Access to customers. ✴️ New in v 1.0.25: Merge Accounts of customers who purchased with different mail addresses. ✴️ New in v 1.1.0: Electronic withdrawal function (modal flow + audit log) ✴️ New in v 1.2.0: Order-confirmation mail with consumer-rights block – withdrawal instructions for redeemable products, waiver acknowledgment for digital-immediate products. ✴️ New in v 1.3.0: Redirect-independent purchase recording, reworked login & access possibilities, impersonation ("log in as user"), freebies (lead capture). ✴️ New in v 1.4.0: Freebie sign-up hardening First things first: What are Stripe Payment Links? Stripe Payment Links are basically hosted checkout pages that you can create directly in the Stripe Dashboard – no coding required. You define a product (or multiple line items) in Stripe. Stripe gives you a unique URL (the “Payment Link”). You can drop this URL behind any button, on any landing page, newsletter, or social media bio. When a customer clicks the link, they’re taken to a secure Stripe Checkout page (PCI compliant, supports all major payment methods, Apple Pay, etc.). After payment, Stripe redirects them back to your success URL. Super simple. But… on its own, Stripe has no idea about your ProcessWire site, your users, or your gated content. That’s where this module jumps in. 🚀 Why another payment module? We at frameless Media often work on small client projects where setting up a full e-commerce shop would be complete overkill. Think: Coaches selling a few courses or workshops Businesses offering a handful of digital products or subscriptions Creators who just need a buy button on a landing page Stripe Payment Links are perfect for this. But: ProcessWire on its own doesn’t handle redirects, user handling, or gated delivery pages. So we built StripePaymentLinks – a lightweight drop-in module to connect Stripe with PW. What it does Handles the redirect back from Stripe Checkout that contains the session id Creates or updates the buyer’s user account Records purchases in a repeater field Manages access to “delivery pages” (only available after purchase) Auto-sends access mails (configurable: never / new users only / always) Provides Bootstrap-based modals for login, password reset, set-password Usage examples Example 1: Sales page + delivery page Sales page has a “Buy now” button (Stripe Payment Link). After checkout, the user is redirected to the delivery page, which is access-protected. → Module logs them in, grants access, and if they’re new: a set-password modal pops up. → An access mail with product links is sent. Example 2: Product without a delivery page Some products don’t need protected pages (e.g. a consulting slot or voucher). → The success redirect goes to a generic thank-you page. → The module shows an access summary block with purchased products and sends the mail. Example 3: Mixed purchase (thank-you + delivery page) A checkout with multiple items: e.g. a “simple product” plus an addon that has its own delivery page. → Thank-you page shows the addon link(s). → The access mail lists all purchased products. Source & License The module is open-source under the MIT License. 👉 GitHub: https://github.com/frameless-at/StripePaymentLinks 👉 ProcessWire modules directory: https://processwire.com/modules/stripe-payment-links/ So yes: if you or your clients just need a few low-barrier buy buttons, not a full-blown webshop, this might be the module you’ve been looking for. If needed we can provide some screenshots and visual examples next week 😉 Happy to hear your thoughts, ideas, and testing feedback! Cheers, Mike
  21. I made a small module called ProcessSiteSettings and thought I’d share it here in case it’s useful to someone. ProcessSiteSettings is a lightweight ProcessWire module for storing and editing global site values in one place. There are already similar modules available, so this is simply another free option with a focus on quick setup, usability, and helpful template snippets. It adds a Settings item to the ProcessWire admin menu and creates one central page for global site values like: copyright text footer content contact info social links SEO / AI summary text images repeaters Repeater Matrix page references other regular PW fields Ofc. add your own fields of choice to it, or delete the ones you don't need! It uses a normal template + page approach instead of a fake config form, so it works much more naturally with ProcessWire fields. It also includes a small helper box on the settings edit screen that shows ready-to-use template snippets for each field. It tries to generate smarter examples depending on the field type, including more complex fields like images, repeaters, matrix items, multi-value fields, etc. Settings Menu: Editing Values, adding/deleting custom fields and shortcut to Fields for quick creation of new ones. Quick helper for showing everything on frontend! Example usage on templates: <?= siteSettings('ss_copyright_text'); ?> <?= siteSettings()->ss_footer_text; ?> <?= $siteSettings->ss_contact_email; ?> The admin is in English and the module is translation-ready. Just install the module, and that's it! Just sharing it here in case someone finds it useful. Download Here: ProcessSiteSettings-v13-fixed.zip
  22. Here is a new module for ProcessWire 2.1 that imports pages from a CSV file. By default it will create new pages from data in the CSV file, but you can also configure it to modify existing pages too (existing pages that have the same title). Please give it a try and let me know how it works for you and if you run into any issues with it. This module is something I've had in the works for awhile, and regularly use on various projects, so figured I should clean it up a bit and release it. Also attached are a couple screenshots from it. How to Install: 1. Download from: https://github.com/r.../ImportPagesCSV 2. Place the file ImportPagesCSV.module in your /site/modules/ directory. 3. In ProcessWire admin, click to 'Modules' and 'Check for new modules'. 4. Click 'install' next to the 'Import Pages CSV' module (under heading 'Import'). Following that, you'll see a new menu option for this module on your Admin > Setup menu. Supported field types for importing:* PageTitle Text Textarea (including normal or TinyMCE) Integer Float Email URL Checkbox (single) *I'll be adding support for multi-value, page-reference and file-based Fieldtypes in a future version.
  23. I wanted a way to chat with my Processwire site and built a Module (PW MCP) and an MCP server to connect into it. It's a private repo at the moment but it can be public if anyone finds it useful. It's basically a way to use the Cursor Chat Ui to query my site, fields, templates and content. Here's part of the readme which explains it better. What Is It? ProcessWire MCP is a bridge between ProcessWire and Cursor IDE (the AI-powered code editor). It lets you query your ProcessWire site's structure and content directly from Cursor's chat interface using natural language. Instead of writing selectors or browsing the admin, you can just ask: "What templates does this site have?" "Show me the fields on the blog-post template" "Search for pages containing 'summer'" "Find all images with 'lake' in the filename" Why I Built It Cursor can see your template files and code in the local directory, but it can't see what's actually in your ProcessWire database — which templates and fields are registered, what pages exist, or what content they contain. With ProcessWire MCP, the AI can: Query the actual database schema (not just parse template files) Look up page content by ID, path, or selector Understand field configurations (types, settings, which templates use them) Search across all text content and find files/images Get RepeaterMatrix content with type labels See file metadata (dimensions, descriptions, URLs) It's the difference between seeing $page->body in code vs. knowing what that page's body actually contains. Architecture Cursor Chat → MCP Server (Node.js) → PHP CLI → ProcessWire API The module consists of: PwMcp — A ProcessWire module with a CLI interface mcp-server — A Node.js server that speaks the Model Context Protocol The CLI can also be used standalone for quick queries from terminal. Available Commands Command Description health Check connection and get site info list-templates List all templates with field counts get-template [name] Get template details and fields list-fields List all fields with types get-field [name] Get field details and usage get-page [id\|path] Get page by ID or path with all field values query-pages [selector] Query pages using PW selectors search [query] Search content across all text fields search-files [query] Search files by name/extension export-schema Export complete site schema Example: Health Check php site/modules/PwMcp/bin/pw-mcp.php health --pretty { "status": "ok", "pwVersion": "3.0.241", "siteName": "www.example.com", "moduleLoaded": true, "counts": { "templates": 45, "fields": 72, "pages": 960 } } Example: Content Search Ask Cursor: "Search for pages containing 'summer'" { "query": "summer", "count": 5, "results": [ { "id": 1764, "title": "Lake District walks in summer", "path": "/guides/lake-district-summer/", "template": "page-guide", "matchedField": "Body", "snippet": "The Lake District offers some of the best walking trails in summer. From gentle lakeside strolls to challenging fell walks..." } ] } Example: File Search Ask Cursor: "Find images with 'lake' in the filename" { "query": "lake", "count": 5, "results": [ { "filename": "lake-windermere-sunset.jpg", "url": "/site/assets/files/1070/lake-windermere-sunset.jpg", "size": 31207, "sizeStr": "30.5 kB", "description": "Sunset over Lake Windermere", "field": "Images", "page": { "id": 1070, "title": "Lake District walks in summer", "path": "/guides/lake-district-summer/" }, "width": 500, "height": 626 } ] } Example: Get Page with All Fields Ask Cursor: "Get the page at /about/" { "id": 1050, "name": "about", "path": "/about/", "url": "/about/", "template": "basic-page", "status": 1, "statusName": "published", "parent": { "id": 1, "path": "/", "title": "Home" }, "numChildren": 5, "created": "2023-05-15T10:30:00+00:00", "modified": "2024-11-20T14:22:00+00:00", "fields": { "title": "About Us", "body": "<p>We are a team of dedicated professionals...</p>", "Images": { "_count": 2, "_files": ["team-photo.jpg", "office.jpg"] } } } Example: RepeaterMatrix Support The module fully supports RepeaterMatrix fields, returning the actual content with type labels: { "matrix": { "_count": 3, "_items": [ { "_typeId": 1, "_typeLabel": "Body", "Body": "<h2>Welcome to our guide</h2><p>This guide covers...</p>", "Images": null }, { "_typeId": 2, "_typeLabel": "FAQs", "faq_question": "What is the best time to visit?", "faq_answer": "The summer months offer the best weather for walking..." }, { "_typeId": 3, "_typeLabel": "Call to Action", "cta_title": "Plan Your Visit", "cta_link": "/contact/" } ] } } So thats the first part done and working. My next plan is to be able to 1. PULL / convert a databse page into a local text file which lists all page properties, fields, template etc 2. edit the file as a local text file 3 PUSH the text file back into PW so that the original content picks up the changes Just having fun and building something useful. Very likely there are similar solutions or better ways to handle this but this suits my workflow ATM. Cheers P
  24. Hi everyone, I’m releasing Liora, a ProcessWire module that turns unanswered searches and incomplete content pages into useful conversations — and turns those conversations into actionable editorial demand. Most site search ends in one of two places: a list of matching pages, or an empty result. That works when the visitor already knows the right words and the database contains an exact match. It is less useful when the real question is comparative, contextual or incomplete: “Which bottle fits this occasion?”, “What does this term mean?”, “What should I try next?”, or simply “I expected to find something here.” Liora adds a second path. It can answer the question, continue with follow-ups, ground the answer in public site content, and record the complete demand signal so an editor can improve the underlying website later. How it works in practice I am already using Liora on LQRS, a large ProcessWire drinks-discovery site. 1. Search no longer stops at “no results” A search such as smoky whisky from Scotland currently has no direct structured record matching the complete phrase. The normal ProcessWire results correctly say that no direct match exists. On the same page, Liora produces a concise AI overview, explains the relevant styles and regions, and links to useful internal sources such as the Scotch Whisky collection and Highlands region. The visitor can then ask a follow-up without starting again. This is important: Liora does not replace the deterministic search results or pretend that a generated answer is a canonical database record. The page shows both layers clearly — a conversational overview and the actual structured matches. 2. A content page can answer the next question At the bottom of selected collection and discovery pages, Liora appears as an “Ask about this collection” surface. The widget knows the current ProcessWire page and can use relevant Atlas excerpts and published Vox discussions when those integrations are enabled. A static collection therefore becomes a useful starting point for questions about selection, comparison, terminology or pairings, while the original page remains the source of truth. 3. A 404 becomes a recovery path On the LQRS 404 page, Liora asks what the visitor expected to find. It can help locate a product, recipe, article or guide instead of leaving the visitor at a dead end. 4. Questions become an editorial backlog Every tracked frontend conversation appears in Setup → Liora Insights. Editors can see repeated unmet searches, the source page, referrer, conversation history, status, model, response time, token usage, cache state, retrieval sources and failures. This is the part I find most useful. The generated answer is immediate help for one visitor; the collected demand shows what the site should fix for everyone. Repeated questions can become better structured data, a missing product page, a clearer explanation, a new guide, improved navigation or a search synonym. What Liora includes A reusable frontend conversation widget and InputfieldLiora. Normal JSON responses and real-time streamed responses. One tracked Thread per visitor conversation with chronological messages. Follow-up continuity that preserves recent constraints. Automatic page, source and referrer attribution. Setup → Liora Insights for review, diagnostics and editorial status. Repeated unmet-demand reporting. Optional Atlas retrieval from indexed public site content. Optional published Vox reviews, questions, replies and discussions. Optional live public search through compatible Squad providers. Optional coarse GeoIP enrichment. Validated light and dark themes. Safe Markdown rendering and verified same-site links. Localized widget text and ready-made language presets. A tracked JSON endpoint for completely custom frontends. Public PHP APIs for direct application use. Architecture Liora deliberately does not store provider credentials or implement low-level AI transport. That remains the responsibility of Squad. Liora owns conversations, tracking, retrieval orchestration, the widget and Insights. Squad owns providers, credentials, model discovery, requests and streaming transport. Atlas can supply excerpts from indexed public site content. Vox can supply published community evidence attached to relevant pages. ProcessWire remains responsible for pages, permissions, sessions, localization and persistence. Atlas, Vox, GeoIP and live web search are optional. Liora works with Squad alone and fails back cleanly when an optional context source is unavailable. Basic integration <?php namespace ProcessWire; if($modules->isInstalled('Liora')) { $liora = $modules->get('Liora'); echo $liora->renderWidget([ 'context' => $page->template->name, 'sourceUrl' => $page->url, 'pageId' => $page->id, 'heading' => 'Still looking? Ask Liora', 'theme' => 'default', ]); } The tracked endpoint itself can remain deliberately thin: <?php namespace ProcessWire; $modules->get('Liora')->handleEndpoint(); The consuming site decides where the widget belongs. Liora never inserts itself automatically and does not take over routes, content models or publishing decisions. Privacy and safety Provider credentials remain in Squad. Raw model HTML is never trusted. Atlas excerpts, community content and web results are treated as untrusted reference material. Same-site links are validated; external destinations can be restricted. CSRF protection, rate limits and conversation ownership checks apply to the tracked endpoint. Liora stores a hashed session owner, not a plaintext session identifier. Raw IP addresses and browser user agents are not stored. Conversation review and destructive actions use separate ProcessWire permissions. Stored conversations are preserved on uninstall by default unless destructive uninstall is explicitly enabled. Requirements ProcessWire 3.0.210 or newer PHP 8.1 or newer An installed and configured Squad module A ProcessWire endpoint page for tracked frontend conversations Installation Copy the Liora directory to /site/modules/Liora/. Refresh modules in ProcessWire and install Liora. Configure at least one active provider in Squad. Review the model, prompt, widget, retrieval, privacy and retention settings. Create or reuse the JSON endpoint page and keep its URL synchronized with Liora configuration. Add the widget, Inputfield or custom frontend only where it belongs in the site architecture. Live examples LQRS search with an AI overview: https://lqrs.com/search/?q=smoky%20whisky%20from%20Scotland Page-aware collection widget: https://lqrs.com/collection/best-drinks-of-france/ Dedicated conversation page: https://lqrs.com/ai/ Links GitHub: https://github.com/mxmsmnv/Liora Download ZIP: https://github.com/mxmsmnv/Liora/archive/refs/heads/main.zip README: https://github.com/mxmsmnv/Liora/blob/main/README.md API documentation: https://github.com/mxmsmnv/Liora/blob/main/API.md Integration guide: https://github.com/mxmsmnv/Liora/blob/main/docs/INTEGRATION.md Issues and support: https://github.com/mxmsmnv/Liora/issues I would especially appreciate feedback about where this pattern is useful outside search: documentation, support, directories, product catalogues, knowledge bases and editorial sites — and how you would turn real visitor questions into better ProcessWire content.
  25. Hi everyone, I’m releasing Lumen, a ProcessWire module for managing Cloudflare Stream video from the page editor and the ProcessWire admin. Lumen adds a dedicated video Fieldtype and Inputfield, handles direct and resumable uploads, follows Cloudflare processing status, and exposes playback, thumbnails and metadata through familiar ProcessWire APIs. What Lumen does Adds a Cloudflare Stream Files Fieldtype and Inputfield. Supports direct uploads and resumable TUS uploads. Stores Stream status, duration, dimensions, category, tags, poster, subtitles, trim points, linked page and view count. Provides HLS URLs, responsive iframe embeds, thumbnails, posters and previews. Supports public playback and private playback with signed Stream tokens. Detects portrait, landscape, square and unknown video orientation. Identifies ready portrait videos that fit a configurable short-form duration. Refreshes pending Stream metadata through bounded LazyCron jobs. Includes local-storage mode for development without a Cloudflare account. Protects expiring signed playback URLs when CloudCache is installed. Provides public upload and metadata APIs for integrations with other modules. Embeds videos in formatted text through [[lumen:...]] shortcodes. Admin workspace Lumen adds Setup → Lumen, where editors can upload videos, browse and filter the library, refresh processing status, inspect metadata, copy embeds and Stream URLs, estimate stored and delivered minutes, configure playback and review diagnostics. The field itself can be added to any required template, so video remains part of the normal ProcessWire content model rather than a separate media system. Pagefile API <?php namespace ProcessWire; if($modules->isInstalled('Lumen')) { $lumen = $modules->get('Lumen'); echo $video->streamEmbedResponsive(); $thumbnail = $video->streamThumbnail(12); $poster = $video->streamPoster(); $ready = $video->streamReady(); $orientation = $lumen->streamOrientation($video); } Trusted integrations can also attach uploaded or local files: $video = $lumen->attachUploadedVideo( $page, 'video', $_FILES['video'], 1024 * 1024 * 1024 ); $video = $lumen->attachLocalVideo($page, 'video', $sourcePath); Textformatter The included Textformatter supports: [[lumen:video_uid]] [[lumen:page_id.field_name]] [[lumen:page_id.field_name:thumb]] Requirements ProcessWire 3.0.255 or newer PHP cURL A Cloudflare account with Stream enabled, unless local-storage mode is used for development Installation Copy the Lumen directory to /site/modules/Lumen/. Refresh modules in the ProcessWire admin and install Lumen. Enable Cloudflare Stream for the account. Create an API token with Stream:Edit permission. Save the Account ID and token in Modules → Configure → Lumen. Open Setup → Lumen and refresh the connection status. Create a Cloudflare Stream Files field and add it to the required templates. Links GitHub: https://github.com/mxmsmnv/Lumen Issues and support: https://github.com/mxmsmnv/Lumen/issues Feedback about field behavior, upload workflows, signed playback and the admin experience is very welcome.
×
×
  • Create New...