Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation since 06/24/2026 in Posts

  1. This week we've ProcessWire 3.0.267 on the dev branch, here are some highlights (commits): The entire WireTests module has been moved into the core. All of the tests now live alongside the classes that they test. The WireTests module is used from the command line. Once installed, you can type "php index.php test" for a list of WireTest commands. If you already have the non-core WireTests module installed, I recommend uninstalling it and installing the core version. More than a dozen new WireTests and API.md documentation files have been added this week (this is where the biggest additions of the week are). Many improvements to the CLI "docs" command, especially with regard to chapter retrieval. New faster $modules->refresh() method from @matjazp New HOWTO-API.md documentation that outlines how to write API.md files for your own modules. New getFresh() and getRaw() methods added to $fields and $templates. These do the same as their $pages method equivalents (getFresh and getRaw), except for fields and templates. This was requested by an agent in AgentTools. This week we also have a new guest blog post! Page's best kept secret: the meta() method Thanks for reading and have a great weekend!
    15 points
  2. Hi everyone, I’m happy to share the first public testing release of Mercato, a ProcessWire-native commerce toolkit. Mercato is not just a “shop template” or a simple cart module. The goal is to provide a flexible commerce layer that works the ProcessWire way: pages, templates, fields, permissions, hooks, and site-level customization. The basic idea is: Your website should not have to become “the shop system”. The shop should become part of your ProcessWire site. Mercato can be used as a full storefront, but it is also designed for custom ProcessWire websites that need commerce features without being forced into a rigid shop structure. What Mercato includes Products as ProcessWire pages Cart and checkout Orders stored as ProcessWire pages Stripe, Mollie, PayPal, bank transfer, and demo payment support Discounts and coupons Inventory handling Preorder and backorder support Digital products and downloads Fulfilment: carrier delivery, store pickup, local delivery Customer records Abandoned checkout recovery tools Refunds and payment operation tracking Webhook/event logs Reports and CSV exports Launch-readiness checklist Public order status and receipt pages Headless/read API surfaces A complete installable demo storefront Demo storefront A fresh install creates a real demo storefront called Arlberg Ceramics. It is not just placeholder content. The demo includes: physical products digital products gift cards product collections product images discounts low-stock products sold-out states preorder/backorder examples checkout policy pages order confirmation pages delivery, pickup, and local delivery scenarios The demo is meant to help developers test the full commerce flow immediately after installation. Existing sites Mercato is designed to add commerce functionality to an existing ProcessWire site without taking over the whole website. It creates Mercato-specific fields, templates, pages, permissions, products, collections, and order storage. It does not remove existing site content. Bundled storefront template files are copied into /site/templates/ only when the target files are missing. Existing template files are not replaced unless template overwrite is explicitly enabled in the module settings. That said, this is a commerce module and it changes the site schema, so please test on a staging copy first and make a backup before installing it on an existing/production site. Current status This is the first public release and should be treated as a testing release. I have tested the installer, demo storefront, checkout flow, admin screens, and basic payment workflows, but I would really appreciate feedback from real ProcessWire projects and different hosting setups. Things I’m especially interested in: installation issues gateway setup issues checkout edge cases admin UX feedback missing hooks or extension points template customization feedback real-world commerce scenarios I have not covered yet Repository GitHub: https://github.com/mxmsmnv/Mercato Requirements ProcessWire 3.0.200+ PHP 8.1+ Final note This is a big personal milestone for me. I have wanted ProcessWire to have a serious, modern commerce foundation for a long time. Mercato is my attempt to build that foundation in a way that respects how ProcessWire developers actually build websites. Feedback, testing, issues, and ideas are very welcome.
    8 points
  3. I'd like to showcase the demo shop for my ProcessWire shop system. The demo lets you explore both the frontend and the administration backend. Feel free to log in, place test orders, and try out the available features. The shop automatically resets to its default state every six hours, so you can't accidentally break anything. If you'd like to receive the email notifications using your real email address, please make sure to delete your order immediately after testing, as your email address will be visible in the backend. Because this shop system is primarily developed for the German market, the demo shop and the documentation are currently available in German only. The "Stammdaten" section and the payment methods cannot be edited in the demo to prevent misuse. Demo: https://demoshop.mholte.de/ I'd be happy to hear your feedback, suggestions, and bug reports.
    8 points
  4. Following up on my earlier comment about the background colour - here's a quick side-by-side to illustrate (bottom of post). The proposed change is simple: lighten --pw-main-background from #eee to #f5f5f5 (a shift of less than 3%) Three reasons it's worth considering: #f5f5f5 is already the background colour used on processwire.com, so it brings the admin in line with the brand. It feels noticeably lighter and less industrial in practice. A few of my clients have used that exact wording. For module builders, it opens up more tonal room to work with subtle layering and contrast. I know it's not quite a single variable change. Borders and dividers calibrated against #eee might need a look too, but it's pretty close. You'll see below that it's just a whisper lighter. But in practice users get brand consistency, general lightness and approachability. In practical terms, this is involves transitioning from 93% to 96% white. Copying in @diogo in case this is useful feedback as the theme evolves and celebrates its birthday around now. And finally, in case it needs to be said, the KonKat theme is clean, considered and feels like a proper step forward for the ProcessWire admin. It's a really thoughtful piece of work by people who sweat the details, so I hope this feedback can be taken in that spirit.
    8 points
  5. Is this the desk setup and keyboard thread? I love seeing people's desk setups. I just cleaned up my desk, so here's mine. Computer is a Macbook Air M5 mounted on a shelf under the desk, running from single thunderbolt cable. Monitors are 27" 4k Dell S2725QC (the cheapest 4k USB-C screens you can buy, but I like them). Keyboard is a Kisnt k85. An ebay thunderbolt 4 hub mounted under the desk feeds the screens and an external drive. A cable management basket under the desk keeps all the cables tidy. Monitors are mounted with arms attached to the rear of the desk. ProcessWire coffee and water bottle are my daily drivers, thanks to @Jonathan Lahijani
    7 points
  6. Update (1.1.1) – image downloads and UI improvements Hi all, A couple of releases on from the grid-view update, with a proper new feature this time. @adrian asked for a way to pull images back out of the library, so downloads are in: every thumbnail now has a download button that hands you the original file, not the table thumbnail. Tick a few images first and instead of separate downloads it bundles the whole selection into a single ZIP. It uses the same selection you already use for bulk edits, so it stays consistent with the rest of the module. A few things around it got nicer too. The small per-thumbnail actions (replace, delete, download, select) now use a custom tooltip instead of the browser's native one, and on a multi-selection they tell you what the action will actually do, e.g. "Download 8 selected as ZIP". And replacing a file in place finally gives proper feedback right on the row, success or error, instead of failing quietly. One under-the-hood change worth a mention: the module no longer loads on anonymous front-end requests. There was no reason for it to run on a normal public page view, so now it doesn't, and a guest hit carries zero overhead. Admin, logged-in editors and front-end inline editing all behave exactly as before, and the hourly de-duplication / where-used maintenance still runs. (thanks @adrian for the nudge on that one too) Feedback and bug reports welcome, Cheers, Mike
    6 points
  7. Hi everyone, I have released a new ProcessWire module: TokenForge. TokenForge is a lightweight JWT/signature toolkit for ProcessWire modules and external API integrations. It creates, signs, validates helper inputs, and caches short-lived JWTs for services that require server-side signed tokens. GitHub: https://github.com/mxmsmnv/TokenForge What it does Generates JWT tokens with HS256, RS256, and ES256. Supports Apple .p8 / EC P-256 keys for ES256. Supports RSA private keys for RS256. Supports shared secrets for HS256. Provides createJwt() and createCachedJwt() APIs for other modules. Uses ProcessWire cache for reusable short-lived provider tokens. Fingerprints cached entries by token options, so changed claims/keys do not accidentally reuse an old token. Includes a superuser-only admin UI with dashboard, quick presets, Apple service setup, JWT generator, diagnostics, cache tools, and activity log. Why I built it I needed Apple WeatherKit support in my Meteo module. Apple WeatherKit requires ES256 JWT generation with an Apple .p8 key, and I did not want that signing logic to live only inside one weather module. So TokenForge is intentionally separate: it can be used by Meteo, but also by other modules or integrations that need JWT-based authentication. Apple support TokenForge includes an Apple-focused preset for services that use signed developer/provider tokens, for example: WeatherKit REST API Apple Maps Server API / MapKit JS tokens APNs token-based authentication App Store Connect API MusicKit / DeviceCheck-style developer tokens The Apple preset helps prepare the usual ES256 structure: issuer/team ID, service identifier, key ID, .p8 private key path, headers and payload. Not only Apple The module also includes starting points for: Android/Firebase-style RS256 service account assertions Samsung-style RS256 service assertions Generic HS256 Generic RS256 Generic ES256 Quick presets include demo signing material, so the generator can be tested immediately. For real integrations, replace the demo identifiers and keys with provider values. Security notes TokenForge does not store generated JWTs, private key contents, or shared secrets in module settings. Recommended production usage is to keep private keys in a file path such as: /site/assets/private/AuthKey_XXXX.p8 and pass private_key_path to TokenForge. Basic example $tokenForge = $modules->get('TokenForge'); $jwt = $tokenForge->createCachedJwt('my_provider_token', [ 'ttl' => 3300, 'algorithm' => 'ES256', 'key_id' => $keyId, 'private_key_path' => $privateKeyPath, 'headers' => [ 'id' => $teamId . '.' . $serviceId, ], 'payload' => [ 'iss' => $teamId, 'iat' => time(), 'exp' => time() + 3600, 'sub' => $serviceId, ], ]); Requirements ProcessWire 3+ PHP 8.1+ OpenSSL extension MIT licensed. Repository: https://github.com/mxmsmnv/TokenForge
    4 points
  8. Hi everyone, I’ve released a new ProcessWire module: Oidc. Oidc adds lightweight OAuth 2.0 and OpenID Connect login to ProcessWire sites. It is meant for projects that need social login or company SSO without a full front-end account-management suite. Repository: https://github.com/mxmsmnv/Oidc What it does Adds OAuth/OIDC login buttons to ProcessWire templates Supports Google, GitHub, LinkedIn, Microsoft, Yandex and Yahoo out of the box Supports custom OIDC providers via discovery URL Works with providers such as Okta, Auth0, Keycloak, authentik, Azure AD and Dex Handles callbacks automatically on frontend pages Supports auto-registration of new ProcessWire users Preserves return URLs through the login flow Includes silent mode for SSO-only sites and intranets Provides hooks for identity resolution, login, registration and provider definitions Verifies OIDC id_token claims with nonce, issuer, audience, expiry and RS256/JWKS checks when available Basic usage After installing and configuring providers, render login buttons in a template: $oidc = $modules->get('Oidc'); echo $oidc->renderButtons(); The page that renders the buttons is also the callback page. Set that URL in the module settings and register the same URL in your OAuth/OIDC provider app. Example use cases Add “Continue with Google” or “Continue with GitHub” to a member area Use Okta/Auth0/Keycloak for company SSO Protect an intranet or private section with silent SSO Auto-create ProcessWire users after successful provider login Add custom rules through hooks, for example restricting registration to a company email domain Documentation The README gives the overview, and the repository includes detailed documentation and agent-readable integration notes: README: https://github.com/mxmsmnv/Oidc Documentation: https://github.com/mxmsmnv/Oidc/blob/main/DOCUMENTATION.md Agent guide: https://github.com/mxmsmnv/Oidc/blob/main/AGENTS.md Requirements ProcessWire 3.0.200+ PHP 8.1+ curl openssl The module is MIT licensed. Feedback, bug reports and suggestions are very welcome.
    3 points
  9. Thanks for your patience. It took me a while to set up a safe demo shop, but it's finally ready. Feel free to log in and place test orders. If you'd like to receive the email notifications using your real email address, please make sure to delete your order immediately after testing, as your email address will be visible in the backend. The demo shop is reset to its default state every six hours. The "Stammdaten" section and the payment methods cannot be edited in the demo to prevent misuse. Please take a look at: https://demoshop.mholte.de/ I'm looking forward to hearing your thoughts and receiving your bug reports.
    3 points
  10. There've been a few instances published about AI models going to extremes to solve a question. It's not that AI is malicious or over-eager to please. It's how it's wired. Find an answer or best guess or stop if there's an off-switch in the prompt when the goal cannot be reached. I have a non-technical client who thinks AI is the bee's knees and the answer to his content/SEO/GEO prayers. Client has no DDEV/SSH/FTP site access or coding knowledge. Claude app navigated the owner to the TracyDebugger console in admin to fulfil the owner's request to update site content. Client had no clue about TD until that moment. Claude did. It took client through a questionnaire about installed modules. Claude only had a 'snapshot' of pages, no holistic understanding of db, templates, etc. Client now thinks TD console is the best thing ever. He asks Claude a question. Claude answers and tells client to copy/paste it into TD console. Am now busy trying to bring Claude under control with audit trails, approvals and convincing client to use @ryan AgentTools to minimise risk. Yes, on live production site. OMG! No matter what your views on AI, it's out there and loves PW.
    3 points
  11. Claude is always asking me to test things via Tracy console. This is why I added to the copy MD for agent, including the Copy All button at the bottom. It lets it understand the file/template/data structure and also to run comparisons on the data retrieved when refactoring code or adding new features. I much prefer this to giving Claude direct access to the site DB - this way I can check each query it's about to make and to choose whether I provide it with the complete results or not. Not that it is a real lock, but Tracy does have a setting to prevent all access to superusers with another role so if they don't know about Tracy then you could keep them out. Best bet would be to define this setting via $config>tracy rather than in the module settings so it's harder for them to override.
    3 points
  12. I agree with @Peter Knight - I set --pw-main-background: #fbfbfb; on all my sites, but I am sure#f5f5f5 would also be a better default.
    3 points
  13. How KeyHelp for ProcessWire was built: from a phone idea to a tested module I have been building modules for ProcessWire for a long time, but this one had a slightly different origin story. KeyHelp started not as a carefully planned “module project”, but as a practical question while I was away from my computer: What if ProcessWire could manage a hosting panel directly from the admin area? The initial research happened on my phone. I was looking at how other systems handle hosting integrations, especially WordPress. WordPress has a huge ecosystem around this: hosting panels, one-click installers, backup plugins, deployment tools, billing integrations, and managed hosting workflows. Panels like HestiaCP, FastPanel, CyberPanel and CloudPanel all have their own approaches to WordPress automation. That made me think about ProcessWire. ProcessWire is a very strong developer CMS, and I have built modules for it for years, but hosting operations usually still live outside the CMS: domain setup, databases, SSL, PHP versions, DNS records, FTP accounts and cron jobs. For editors and site owners, that means switching between the CMS and the hosting panel. For developers, it means repeating small operational tasks that could probably live closer to the project. The research then moved toward German hosting panels. I used Google Gemini on my phone to explore that landscape. The conversation started around hosting panel integrations, WordPress automation, CloudPanel, CLI/API wrappers and then German panels specifically. KeyHelp stood out because it is widely used in the German hosting world and has a REST API. I also looked at the broader German ecosystem: LiveConfig, Froxlor, older i-MSCP setups, and custom panels from German hosts like All-Inkl and Mittwald. That context mattered, because KeyHelp is not just “another control panel”. It belongs to a hosting culture where stability, server control and GDPR-friendly infrastructure matter. After that research, I moved to Claude on my phone for the first implementation attempt. The first prompt was essentially: Need build integration module with KeyHelp web panel for administration Webserver inside PW Then I defined the first scope: Domains: create, delete, list Clients / users Databases Email accounts SSL / Let’s Encrypt PHP settings DNS records A ProcessWire admin dashboard with server status, domains and database widgets API access through a KeyHelp admin key Claude produced the first module draft. It created the initial structure with a module file, assets, views, dashboard, domain list, create forms, SSL/PHP/DNS screens, client views, database screens and basic cache/API handling. But the first version was too monolithic. So the next correction was immediate: Do not make it a monolith. Put the settings into the module. Where is the Process module? That changed the architecture. The module was split into: KeyHelp.module.php for configuration, API client, cache, debug logging and module settings ProcessKeyHelp.module.php for the ProcessWire admin UI later, multiple traits under src/ProcessKeyHelp/ views under views/ CSS/JS and Remix Icon SVG assets under assets/ That was the first important turn: not just “make something that works”, but make it feel like a real ProcessWire module. Claude also helped shape the first permission model. The early version was basically superuser-only, but it became clear that a real module needed ProcessWire permissions. The model became: keyhelp-view keyhelp-edit keyhelp-delete keyhelp-server So even before the heavy testing phase, the direction was already moving from “prototype” to “proper ProcessWire admin module”. When I got home, I saved the generated module, opened the module folder in Codex, and the real work began. At that point I also decided to buy a fresh Hetzner test server specifically for this module. That turned into its own small side quest: I had to create a Hetzner account, go through identity verification, take a photo of my government ID / driver license, take a selfie, submit everything, and wait for approval before I could even create the server. Only after that could I create the VPS, install KeyHelp, connect it to a real domain, create an API key and start testing the ProcessWire module against a real hosting panel. The server uptime later showed: 17h 12m That became a nice marker of the whole process. This was not just a fake UI built against assumptions. There was a real KeyHelp panel, a real API key, a real ProcessWire installation, and a real remote server used specifically to test the integration properly. The first real problem appeared immediately in ProcessWire: Cannot reach KeyHelp API: cURL: Could not resolve host: key.smnv.org That led to the first practical improvements in Codex: API URL handling; API access notes; SSL verification settings; DNS resolution override; better module configuration hints; safer debug logging. The KeyHelp panel showed API version 2.14, so the implementation was aligned with the KeyHelp REST API docs. From there, the module became a loop of implementation, browser testing, corrections and UI review. This was the main Codex phase. I had Chrome open with two real things side by side: the KeyHelp panel on the test server; the ProcessWire admin module running on my site. Codex was editing the module files locally, and I was checking the result in the browser. I asked it to click through pages, inspect forms, open tabs, check GET/POST behavior, test UI states, and compare the result with what I saw. The module was tested in Chrome and in the in-app browser across: dashboard domains domain view SSL tab PHP tab DNS tab clients databases email FTP SSL certificates cron jobs installer server page module settings A lot of the work was not glamorous. It was small things that make a module feel real: tabs did not work correctly at one point; buttons had unwanted underlines; Font Awesome icons were jumping because more than one icon set was involved; icons were replaced with Remix Icon SVGs; tables were too custom and started hiding API data; badges were too small; breadcrumbs were inconsistent; some titles and breadcrumbs were not translated; German labels were missing in places; uk-table-small, uk-margin-remove, kh-mono and other styling leftovers had to be removed; dashboard and server screens needed better information layout; module settings needed better UI/UX; slow API pages initially felt frozen, so lazy background loading was added. This is where the human + AI workflow was useful. Codex would implement a change. Then I would look at the browser and say things like: “the tabs are broken” “what happened to the design?” “why is there a big left gap?” “the icons jump” “this table is wrong” “the German version still says Refresh” “this should look like Ichiban” “remove custom table styles” “don’t use Font Awesome” “test this in Chrome” “go through all tabs yourself” Then Codex would inspect the code, patch it, test again, and refine the result. There was also a strong UI direction: the module should not look like a random SaaS dashboard. It should feel like a ProcessWire admin tool. Dense, calm, useful, and close to the Ichiban / AdminThemeUikit style. No decorative landing page, no marketing hero, no unnecessary cards inside cards. The installer became the biggest feature. The goal was: From ProcessWire Admin, choose a KeyHelp domain, choose ProcessWire stable or dev, and let the module install ProcessWire there. That meant the module needed to: resolve the domain document root; support the case where KeyHelp and ProcessWire run on different hosts; support local and SSH remote deployment; download the ProcessWire archive; unpack it; create a KeyHelp database and database user; generate a random admin URL; generate secure credentials; run the ProcessWire CLI installer; adapt Apache configuration for KeyHelp; remove installer files; store credentials securely. At first, the installer assumed the document root was visible locally. That was wrong for real deployments. The KeyHelp panel can be on one server and the ProcessWire admin module on another. So the installer had to learn the difference between local filesystem and remote SSH deployment. That was a very important correction. The module should not only work on my local setup. It should handle the realistic case where the ProcessWire admin site and the KeyHelp hosting server are separate machines. Then came another important question: After ProcessWire is installed, where are the generated credentials stored? The answer became: in a module-managed table, encrypted using the ProcessWire site salt. The domain list now shows a ProcessWire badge when an installation is known, and the domain detail page can show stored admin URL, admin login and database credentials to users with the right permission. There is also a GitHub module installer for already installed ProcessWire sites. It checks whether ProcessWire exists in the target path, downloads a GitHub repository archive, validates PHP syntax, and copies it into /site/modules. The server page also evolved during testing. At first it was too raw. Then it became a proper admin view with: server information; software versions; resource usage; services; server reboot action; links back to KeyHelp where the API does not expose something. A specific note was added because the KeyHelp REST API does not expose start/stop/restart endpoints for individual services. Server-level reboot is available through POST /server/reboot for KeyHelp 26.0+. Debugging support was added too. The module can log sanitized API requests, payloads, responses, cache hits and timings to keyhelp-debug, while redacting sensitive values like API keys, passwords, tokens and secrets. One of the important late-stage changes was performance. Some KeyHelp API calls could take many seconds. At one point Tracy showed pages taking a long time because data was being fetched directly before the admin page rendered. That is bad UX: it makes the admin feel frozen. So the module was changed so slow API-backed pages render an admin shell first, then load data in the background. The user sees that the page is alive, and the data fills in when ready. The module also gained English and German UI support. Since KeyHelp is a German hosting panel, German translation was not just a nice extra. It made sense for the module’s audience. The documentation evolved during the same process: README was rewritten in a release-ready style; German documentation was added; CHANGELOG was made first-release friendly with only an Added section; sponsorship metadata was added; version was set to 100; AGENTS.md was added so future AI agents understand how to work with the module, what not to touch, how the installer works, what API calls exist, and how to test safely. Near the end, the repository was cleaned up: the monolith was split into src/, views/ and assets/; tests were kept local and ignored; unused generated image assets were removed; README was kept version-free; the GitHub branch was recreated using an orphan commit so the public repository starts cleanly with one init commit. The final result is not only a KeyHelp API wrapper. It is a ProcessWire admin integration for a German hosting panel, with a real installer workflow for creating ProcessWire sites on KeyHelp domains. The full path looked roughly like this: I researched hosting integrations and German panels with Google Gemini on my phone. I used Claude on my phone to create the first KeyHelp module prototype. I corrected the architecture so it became a real ProcessWire module pair instead of a monolith. I created a Hetzner account and went through ID/selfie verification. I bought a fresh test server specifically for this module. I installed KeyHelp on the server. I saved the generated module locally. I opened the module folder in Codex. I connected the module to the real KeyHelp API. I tested the UI and API workflows in Chrome. I repeatedly corrected UX, tables, icons, tabs, translations and layouts. I added the ProcessWire installer. I added SSH remote deployment. I added encrypted credential storage. I added GitHub module installation for existing ProcessWire sites. I added lazy loading for slow API pages. I cleaned up README, German docs, CHANGELOG and release metadata. I published the repository as a clean orphan init commit. This is what I found interesting about the process: the AI did not replace testing or product judgment. Gemini helped with research and context. Claude helped create the first prototype. Codex helped turn it into a tested module by repeatedly editing code, running checks, using Chrome, and reacting to very specific feedback from the real UI. The quality came from the loop: build, open in browser, click, notice what feels wrong, fix, test again. The test server uptime, 17h 12m, is a funny detail, but it captures the mood of the whole thing: a fresh server bought just to make sure this module was not theoretical. Repository: https://github.com/mxmsmnv/KeyHelp
    2 points
  14. My print-on-demand webapp is very complex. It has: hundreds of fields tens of thousands of pages (let's focus on orders) listers (again, let's focus on my "Orders" lister) many filters on listers (my Orders lister has about 20 filters) When you load a ListerPro lister page, it technically does 2 requests: first request is to build the interface second request (ajax) loads the results based on the filters, etc. I noticed it became very slow over time, but I didn't look into it deeply until now. Even though I have thousands of order pages, that's actually not the issue. First, part of the issue is what type of page reference fields you are using, which I wrote a tutorial about, so make sure to view that as well. (also keep in mind TracyDebugger slows things down a lot here as well) But even with that, it's still slow on the first request. It would take 8-14 seconds to load a ListerPro page on the first request! The issue? Having too many filters (20 for example) combined with the fact my site has hundreds of fields means that generating that filters list is incredibly intensive. That filters list is powered by the InputfieldSelector field. I worked with DeepSeek and it came up with a simple solution: when rendering the field list (ie, the first dropdown in InputfieldSelector), don't show every single field as an option... instead only grab the fields that I have actually used. This keeps the InputfieldSelector field working correctly, but eliminates a bunch of fields I wouldn't have wanted to use in my filters anyway. So, we're sacrificing a little (unneeded) flexibility for extreme performance gain. Now my ListerPro page loads in less than a second! Use this hook in ready.php: if(wire('page')->process == 'ProcessPageListerPro' && !wire('config')->ajax && wire('input')->urlSegment1 !== 'config') { wire()->addHookBefore('InputfieldSelector::render', function($event) { $is = $event->object; // Don't interfere if limitFields was already explicitly configured $existing = $is->limitFields; if(!empty($existing)) return; // Parse field names from the current selector value $value = (string) $is->attr('value'); if(!strlen($value)) return; $fieldNames = []; try { $selectors = wire(new \ProcessWire\Selectors($value)); foreach($selectors as $s) { foreach($s->fields as $field) { if(strpos($field, '.') !== false) { list($field,) = explode('.', $field, 2); } $fieldNames[$field] = $field; } } } catch(\Exception $e) { return; } // Always include system fields (needed for the template row) foreach(['id','name','title','template','parent','status', 'created','modified','published','path','has_parent', 'created_users_id','modified_users_id','num_children', 'count','include','limit','sort','_custom'] as $f) { $fieldNames[$f] = $f; } if(count($fieldNames)) { $is->set('limitFields', array_values($fieldNames)); } }); }
    2 points
  15. Verk 1.5.0 is out. This release includes the recent task/status and editorial workflow improvements, plus a cleanup of the module internals: inline task status dropdowns on Dashboard and Tasks email notifications for newly assigned/collaborating/reviewing users hidden/unpublished/trashed page status indicators user-scoped Content Audit rules several Dashboard, Tasks, Calendar, pagination, and editor layout refinements the former Verk.module.php monolith is now split into src/Traits and src/Services, with Verk.module.php kept as the ProcessWire entrypoint ProcessWire module version is now 150, so run Modules > Refresh after updating. Big thanks to Adrian for the PRs, testing, screenshots, and follow-up feedback that helped shape a lot of this release. @adrian
    2 points
  16. @szabesz As far as I know, there isn't any reason why a moved InputfieldSelectMultiple should cause an error on any URLs that don't actually use that module. So if you can go to a URL like the login page or modules page or anything other than a page editor page that's using SelectMultiple or AsmSelect, that should work. But If you are still getting an error, even if a page isn't using that module, then there may be some other issue at play. You can try to refresh the modules manually from the terminal by typing "php index.php modules refresh" in your web root. Another option is to temporarily copy the wire/modules/Inputfield/InputfieldSelect/InputfieldSelectMultiple.module file into wire/modules/Inputfield/ (its previous location), then do a Modules > Refresh. It will tell you that it found two copies of the same module, click the link it gives you to choose which one you want. Select the one in wire/modules/Inputfield/InputfieldSelect/, and save.
    2 points
  17. Hey @jploch Thanks for jumping in and providing your design thinking. All solid reasons.
    2 points
  18. I would prefer #fbfbfb; too. That's what I change the background color to on my sites too.
    2 points
  19. @HMCB, happy you like it! Everything is handled by PW, no need to change anything in your templates or editing behavior. The module is admin-only and never touches front-end rendering. In templates you use the normal API ($image->size(), ->width(), ->url, …) and PW generates/serves variations exactly as always. Rename: PW has no immutable ID column for files. The filename is the identity (stored in the field’s data column). So a rename is a real on-disk rename, and PW core (Pageimage::rename(), 3.0.172+) cascades it: the original plus every size variation (foo.300x200.jpg → bar.300x200.jpg) and any .webp sidecars are moved, not deleted or regenerated. The new name is committed on the next $page->save(). Our module adds two things on top: it re-keys its dedup fingerprint rows and rewrites rich-text embeds that referenced the old URL, so disk, DB, dedup index and embeds stay consistent. For a new project I would strongly recommend having a look at @Peter Knights MediaHub instead! The main purpose of the module was to handle existing installations. Cheers, Mike
    2 points
  20. Yep, that was the main motivation behind this implementation. Now I only have to touch one file per template.
    2 points
  21. Hi everyone, Accessibility overlays have a bad reputation — mostly because they're sold as SaaS, phone home to third-party servers, and charge monthly fees for something that should be built-in. Ally is different: self-hosted, MIT, no external requests at runtime. GitHub: https://github.com/mxmsmnv/Ally What it does Adds an accessibility panel to your site's frontend, powered by Sienna (MIT). The JS bundle and OpenDyslexic font ship with the module and are served from your own server — nothing loads from external CDNs at runtime. Font size adjustment Dark, light, and high contrast modes High/low saturation, monochrome Dyslexia-friendly font (OpenDyslexic, bundled locally) Highlight links and headings Letter spacing, line height, bold text Reading guide, stop animations, big cursor 53 languages with auto-detection from html[lang] or browser settings Full ProcessWire multi-language support — maps $user->language to the correct locale automatically Configurable position, offset, button size, and accent color Skips admin pages and Chrome Lighthouse by default No build step — prebuilt JS bundle included. One caveat: the widget is injected via Page::render hook. If you serve pages through ProCache static HTML, the hook doesn't run on cached pages — exclude those pages from ProCache if you need the widget there. Overlay widgets supplement, but do not replace, accessible markup. Use Ally alongside good semantic HTML, not instead of it. Requirements: ProcessWire 3.0.200+, PHP 8.1+ MIT License.
    2 points
  22. Hi everyone, a client of ours had a term that shows up all over their site, and they had it registered internationally. So suddenly it needed an ® after every occurrence. The question landed in our inbox as "you probably know an easy way to do this, right?" 😉 There is already Ryan's TextformatterFindReplace, which is powerful and the right tool if you are happy writing regex. We needed something different: a textformatter our clients can edit themselves, i.e. people who do not write regular expressions. So in Annotations you just list the strings and pick options in a small per-string table, no regex anywhere. And so clients never have to touch the Modules section, the module also adds its own page under Setup, guarded by a dedicated annotations-edit permission, where they manage exactly these settings and nothing else. What it can do, for example: Append a mark, the classic case: put (R) (or ©, ™, ...) after a term wherever it appears. Wrap a part of a word, e.g. turn H2O into H2O (subscript the 2). Auto-style certain terms, e.g. make a brand name bold everywhere. Footnote markers, mark only the first occurrence of a term (first-only), great for footnotes1. The real work, though, is in the details that make it safe to hand to an editor: It only changes text, never markup. Tags and their attributes (href, alt, title, class), HTML comments, and the content of skip-tags you configure (code, pre, script, style) are left completely alone. A brand name sitting in a URL or an alt text stays untouched. E-mail addresses are protected. With a frameless to ® rule, info@frameless.at does not turn into info@frameless®.at. It never doubles a mark. It recognises a symbol that is already there, whether it was typed as the literal character (®), as an entity (®, ®, ®, ®, lower or upper case, even with leading zeros), or already wrapped in a tag. No second one gets added. It normalises messy input to your setting. Same spelling, consistent form: a bare symbol gets wrapped, an existing wrapper gets unwrapped (or re-wrapped) if you change the tag later. Editors can be inconsistent and the output still comes out uniform. Longest match wins, and rules compose. Configure both "frameless" and "frameless Media" and each keeps its own treatment. Append runs first, wrap layers on top, so "frameless Media" can be bolded on the word and still get its ® at the end: frameless Media®, while a single "frameless" gets rendered as frameless®. Per-string control: whole-word matching (so cat does not hit category), case sensitivity, and first-occurrence-only, each set per string. Any inline wrap tag: sub, sup, b, strong, em, mark, abbr and more, not just superscript. Get it here https://github.com/frameless-at/TextformatterAnnotations https://processwire.com/modules/textformatter-annotations/ Feedback and ideas welcome. Cheers, Mike!
    2 points
  23. Hi everyone, As promised, the Beta version of WireBooking is now available on GitHub! You can find the repository here: https://github.com/markusthomas/WireBooking I would love to get your feedback on the installation process and general usability. If you find any bugs or have suggestions for improvements, please open an issue on GitHub. Happy testing!
    2 points
  24. Hi @eutervogel! I am extremely surprised and impressed. This shop "module" basically came out of nowhere and solves a huge "black hole" in the ProcessWire community: A functional, up-to date and all-in-one shop solution. I made a shop with Padloper (Version 1) years ago which was one of my first PW projects ever. And in my main job I am working for one of germanys biggest e-commerce shops. Coming that way I now what immense work setting up, developing and not least maintaining an online shop is nowadays. You have tons or regularities that you have to take care of and each year something is added. For example: Last year all bigger online shops had to be be overworked due to the German Accessibility Improvement Act now the latest "addition" was the integration of the "electronic cancellation button". If you offer a shop solution for a client based on an existing system or "custom made" - you have to be in constant awareness of the legal changes and act immediately. Then you have to design the landing page, category pages, product pages, the checkout pages, search pages and the whole customer backend. Not to mention many many e-mail templates. Because of that the last shop that I set up for a client was actually a Shopify solution. That still was a ton of work, especially if you consider the countless hours for reading the developer docs and becoming familiar with the Shopify CLI and the whole template/development system (and so on!). So it's nice to see that there is a PW alternative now. I like the fact that everything is integrated and the documentation seems to be extremely well planned. I can remember that there was another shop module for PW around that looked promising but offered little to no documentation at all. What a bummer.
    1 point
  25. WireWall 1.6.0 Released: Traffic History, AI-Ready Logs, and Dashboard Redesign Hi everyone, I’ve released WireWall 1.6.0, a new update for the ProcessWire firewall/security module. This release focuses on better traffic visibility, AI-assisted analysis, and a cleaner admin dashboard. What’s new AI-friendly traffic history WireWall can now save public request history as daily JSONL files: /site/assets/WireWall/traffic/traffic-YYYY-MM-DD.jsonl Each row contains structured request data such as: time allowed / blocked status block reason IP country city / region when available ASN method URL path and query referer User-Agent selected request headers This is separate from the normal ProcessWire log and is intended for later traffic analysis, including feeding recent traffic into AI tools. New setting A new option was added: Save Traffic History It is enabled by default and can be managed from the WireWall module settings. Dashboard redesign The Admin > Setup > WireWall dashboard has been redesigned with: clearer status header protection/logging indicators improved KPI cards better active bans view cleaner top reasons/countries/IPs sections more readable recent events table traffic history status and path display Agent-readable documentation This release also adds AGENTS.md, describing how AI agents and Olivia-style assistants should safely work with the module, including configuration keys, safe/risky operations, and website blueprint guidance. Version Current version: 1.6.0 Release: https://github.com/mxmsmnv/WireWall/releases/tag/v1.6.0 Repository: https://github.com/mxmsmnv/WireWall Feedback, bug reports, and configuration ideas are very welcome.
    1 point
  26. Hey @maximus, great work as always, I’m definitely going to give this module a try! Thanks!
    1 point
  27. Hi everyone, I have released a new ProcessWire module: KeyHelp. KeyHelp is a ProcessWire admin module for working with KeyHelp, a German hosting control panel. It brings common KeyHelp hosting tasks into ProcessWire Admin, and it can also install fresh ProcessWire sites directly on KeyHelp domains. Repository: https://github.com/mxmsmnv/KeyHelp What it does The module adds a dedicated KeyHelp section in ProcessWire Admin where you can: view a hosting dashboard with server status and resource counts; browse and manage domains, clients, databases, email accounts, FTP users, SSL certificates and cron jobs; update per-domain SSL, Let's Encrypt, HTTPS redirect, HSTS, PHP version and DNS records; open KeyHelp database tools / phpMyAdmin links from ProcessWire; view server information, software versions, resources and service status; cache KeyHelp API responses and flush the cache manually; enable sanitized debug logging; use English or German UI text; restrict the module to one KeyHelp client in single-tenant mode. Screenshots ProcessWire installer The installer can create a fresh ProcessWire site on a selected KeyHelp domain. It can: download the stable or dev ProcessWire archive; unpack it into the domain document root; create a KeyHelp database and database user; generate a random admin URL and strong credentials; run the ProcessWire CLI installer; adapt Apache configuration for KeyHelp; store generated credentials encrypted with the ProcessWire site salt; show a ProcessWire badge and credentials on the domain detail page. It supports both local installs and SSH remote installs, so the ProcessWire admin site and the KeyHelp hosting server do not have to be the same machine. There is also a GitHub module installer for already installed ProcessWire sites. It checks the target installation, downloads a GitHub repository archive, validates PHP syntax and copies the module into /site/modules. Requirements ProcessWire 3.0.200+ PHP 8.0+ PHP curl extension KeyHelp REST API access KeyHelp admin API key The module targets KeyHelp API 2.14 and /api/v2 endpoints. Permissions The module adds granular ProcessWire permissions: keyhelp-view keyhelp-edit keyhelp-delete keyhelp-server Superusers always have access. Notes This is the first public release, so feedback is very welcome, especially from anyone using KeyHelp in production or testing ProcessWire deployment workflows. I built it because I wanted to manage hosting operations from inside ProcessWire instead of switching back and forth between the CMS and the hosting panel. The installer is also meant to make it easier to spin up ProcessWire sites on KeyHelp domains. German documentation is included in the repository. Author: Maxim Semenov Website: smnv.org Repository: github.com/mxmsmnv/KeyHelp
    1 point
  28. Hi all 👋 AiWire is now Squad. Same module, same author, cleaner name — and a lot more under the hood since the last release. If you were using AiWire, this is your upgrade-and-rename notice; if you're new, here's the short version. What Squad is A provider-independent AI gateway for ProcessWire. You write your code once against a simple API ($squad->ask(...)) and switch model/provider with a single option — no provider-specific glue in your templates. What's new since AiWire 14 providers through one API — Anthropic, OpenAI, Google, xAI, OpenRouter, plus direct Chinese providers: DeepSeek, Qwen (Alibaba), Moonshot/Kimi, Zhipu/GLM, MiniMax, 01.AI/Yi, Doubao, Ernie (Baidu), Hunyuan (Tencent). Embeddings — embed() for vectors (OpenAI / Google / Qwen / Zhipu), single or batched. Images — image() (xAI Grok Imagine, OpenAI gpt-image-1). Agentic tool-use — run() runs the full tool-calling loop for you (OpenAI/Anthropic differences normalized). Encrypted key storage — keys live encrypted at rest (libsodium); a DB dump shows only ciphertext. You can also reference an env var with env:MY_KEY so nothing secret hits the database. Prompt caching, adaptive-aware model handling, and a refreshed model catalog (Opus 4.8 default, Fable 5, current GPT/Gemini/Grok). Familiar helpers kept: chat(), ask(), fallback chains, multi-key rotation, per-page file caching, save-to-field. Migrating from AiWire (order matters) Install Squad first — it auto-migrates your key table and settings (your encrypted keys are preserved). Then uninstall AiWire. ⚠️ Do it in that order. Uninstalling AiWire first drops the old key table, so you'd have to re-enter keys. Links & requirements GitHub: https://github.com/mxmsmnv/Squad (old AiWire links redirect) Requires ProcessWire 3.0.210+ and PHP 8.1+ MIT, by me — smnv.org Feedback and issues welcome. Thanks to everyone who tried AiWire — Squad is where it grows from here. 🚀
    1 point
  29. @ryan Great update! Since the blog post is about $page->meta(), I wanted to share my pull request from 2022 that adds meta support to the pages export/import module 😊: It adds support for exporting/importing $page->meta() data via core ProcessPagesExportImport Module. Tested with multiple pages and works well so far. I made changes to the PagesExportImport Module, but it might be better to implement this in the core PagesExportImport Class. That would make the feature available to the API and other modules as well. But I am not sure how to do that, because to import the meta data, the pages must be created first, so the code might only work in the module, after the pages are created. It would be a nice addition in general, and especially for PageGrid, since it uses meta data for layout and settings. Right now meta data is no being exported/imported at all. The fix should not be too complicated. Maybe you can ask your agent about this 😊
    1 point
  30. Hello everyone, I have been working on PWGermanShop, a comprehensive shop system built specifically for ProcessWire to address the regulatory and functional requirements of the German market. The system is nearing its final stages, and I am now looking for a small group of testers to help gather real-world feedback before a wider release. Since the ProcessWire forum is international, I am writing this post in English. However, please note that both the system and its documentation are currently only available in German, as the project is tailored to the DACH region. What is PWGermanShop? PWGermanShop is designed to handle the typical workflows and legal requirements of German e-commerce setups within ProcessWire. You can read through the documentation here to see how it works: 👉 https://mholte.de/docs/PWGermanShop/ How to participate in the test: The system is currently not publicly downloadable. I would like to share the installation files individually with interested testers to ensure a structured feedback process. If you are a ProcessWire developer building sites for the German-speaking market and would like to test the system: Please read the documentation to see if it fits your general requirements. Reply to this thread or send me a private message (PM) if you would like to participate. I will then send you the download link and instructions on how to install it. What kind of feedback is helpful? Is the setup and configuration process logical? Does the documentation cover all the steps clearly? Are there any bugs or edge cases you encounter during your tests? Thank you very much for your interest and support. I look forward to your feedback and to collaborating with some of you! Best regards
    1 point
  31. @szabesz My best guess is that there must be some other module that is loading AsmSelect, and doing so on every page load. That would explain the error. I've upgraded a few installations and haven't seen this error, but if it starts appearing for more people then we'd have to identify what's in common among those installs. It's possibly a load order issue, which might be solved by asmSelect moving its getModuleInfo() array to a separate InputfieldAsmSelect.module.info file. ProcessWire should already do a modules refresh on every version update, but it looks like this error popped up before it could do the refresh.
    1 point
  32. Yes. Composer is only needed to build the `vendor/` folder; the module does not need Composer on the server at runtime. You can run this locally: cd /path/to/site/assets/GeoIP/ composer require geoip2/geoip2 Then upload the whole `site/assets/GeoIP/` folder to the server, including: site/assets/GeoIP/vendor/autoload.php site/assets/GeoIP/GeoLite2-City.mmdb The module looks for the autoloader at: site/assets/GeoIP/vendor/autoload.php So as long as that file and the GeoLite2 database are there, it should work without Composer installed on the hosting server.
    1 point
  33. Meteo update: Apple WeatherKit provider Small update for Meteo: Apple WeatherKit support has been added. Meteo now supports these providers: Open-Meteo OpenWeatherMap WeatherAPI.com Apple WeatherKit Apple WeatherKit uses Apple REST API authentication and requires ES256 JWT tokens. For that part Meteo now uses a separate helper module, TokenForge, which handles JWT generation and caching. Meteo repository: https://github.com/mxmsmnv/Meteo TokenForge repository: https://github.com/mxmsmnv/TokenForge Apple WeatherKit requirements To use the Apple provider you need: Apple Developer account Team ID WeatherKit Services ID Key ID downloaded Apple .p8 private key TokenForge installed Recommended key location is a private, non-public path such as: /site/assets/private/AuthKey_YOURKEYID.p8 Meteo asks TokenForge to create and cache the short-lived WeatherKit JWT, then sends it as a Bearer token to Apple WeatherKit. This update is in Meteo 1.1.0.
    1 point
  34. This module facilitates quick batch creation (titles only or CSV import for other fields), editing, sorting, deletion, and CSV export of all children under a given page. You can even provide an alternate parent page which allows for editing of an external page tree. http://modules.processwire.com/modules/batch-child-editor/ https://github.com/adrianbj/BatchChildEditor The interface can be added to the Children Tab, or in a new dedicated tab, or placed inline with other fields in the Content tab. Various modes allow you to: Lister - Embeds a customized Lister interface. Installation of ListerPro will allow inline ajax editing of displayed fields. Edit - This allows you to rename existing child pages and add new child pages. It is non-destructive and so could be used on child pages that have their own children or other content fields (not just title). It includes the ability to quickly sort and delete pages and change page templates. Also allows full editing of each page via a modal dialog by clicking on the page name link. This is my preferred default setup - see how it replaces the default Children/Subpages with an easily addable/editable/sortable/renamable/deletable list. Note that the edit links open each child page in a modal for quick editing of all fields. Add - adds newly entered page titles as child pages to the list of existing siblings. You could create a list of pages in Word or whatever and just paste them in here and viola! This screenshot shows the editor in its own tab (name is configurable) and shows some of the CSV creation options. Update and Replace modes look fairly similar but show existing page titles. Update - Updates the titles (and any other fields if you enter CSV data) for the existing pages and adds any additionally entered pages. Replace - Works similarly to Add, but replaces all the existing children. There are checks that prevent this method working if there are any child pages with their own children or other content fields that are not empty. This check can be disabled in the module config settings, but please be very careful with this. Export to CSV - Generates a CSV file containing the fields for all child pages. Fields to be exported can to fixed or customizable by the user. Also includes an API export method. Populating fields on new pages In Add, Update, and Replace modes you can enter CSV formatted rows to populate all text/numeric fields, making for an extremely quick way of creating new pages and populating their content fields. Predefined Field Pairings Like the field connections setup from Ryan's CSV Importer, but defined ahead of time so the dev controls what columns from the CSV pair with which PW fields. This is especially powerful in Update mode giving editors the ability to periodically import a CSV file to update only certain fields on a entire set of child pages. These pairings also allow for importing fieldtypes with subfields - verified to work for Profields Textareas and MapMarker fields, but I think should work for most others as well - let me know if you find any that don't work. Access permission This module requires a new permission: "batch-child-editor". This permission is created automatically on install and is added to the superuser role, but it is up to the developer to add the permission to other roles as required. Config Settings This module is HIGHLY configurable down to setting up custom descriptions and notes for your editors. You define one config globally for the site and then optionally you can define completely custom configurations for each page tree parent on your site. There are too many settings to bother showing here - you really just need to look through all the options and play around with them!
    1 point
  35. Hi @Robin S - sorry for delay in responding, but thanks for the follow up. I haven't used that module regularly in so long. Anyway, glad you figured out an approach that works for you. Cheers.
    1 point
  36. NativeAnalytics has been updated to version 1.0.30. This is a small maintenance release with a few focused fixes: Fixed the analytics page widget appearing in field-limited edit interfaces, such as image/file edit modals. Improved PrivacyWire integration so consent changes are synced immediately in the same browser tab. Added a PrivacyWire consent version check to prevent stale consent from older PrivacyWire versions being reused. Fixed a dashboard tab display flash where the Overview tab could briefly appear before the requested tab was activated. Thanks to @adrian for reporting the widget issue and for the helpful pull requests. As always, please refresh modules after updating.
    1 point
  37. Psy, your experience reminds me of well-known AI YouTuber Alex Finn. His AI agent autonomously purchased a phone number, connected to the ChatGPT Voice API and called him to request access to something. I think his setup was running autonomous agents permanently on a Mac mini and he gives them a limited amount of credit card access.
    1 point
  38. Simply amazing. This will go into all of my PW installs. Thank you big time. Questions: Image sizes for the front end are handled like we normally do through PW? If an image is renamed, the alternate size versions are also or does PW handle that through an ID column which never changes?
    1 point
  39. This week we have ProcessWire 3.0.266 on the dev branch. The focus of this version has primarily been on expanding our documentation tools and API.md documentation files. As part of the process, WireTests files are added for each documented class. In addition, the WireApiDocs class got several major upgrades, plus its own documentation file: https://processwire.com/api/ref/wire-api-docs/ Other classes that gained custom API.md documentation and tests files this week were: Fieldtype: https://processwire.com/api/ref/fieldtype/ Selectors and Selector: https://processwire.com/api/ref/selectors/ Pages Versions: https://processwire.com/api/ref/pages-versions/ Wire Markup Regions: https://processwire.com/api/ref/wire-markup-regions/ Wire Text Tools: https://processwire.com/api/ref/wire-text-tools/ Wire Random: https://processwire.com/api/ref/wire-random/ Wire API Docs: https://processwire.com/api/ref/wire-api-docs/ The Fieldtype API.md was written by Claude Sonnet, Selectors/Selector was written by Claude Opus, PagesVersions was written by Kimi K2.7 and the rest were written by MiMo Pro. Each goes through multiple rounds of proofreading and testing. Proofreading is either done by GPT 5.5 or Claude Sonnet. Following that, GPT 5.5 builds tests for the class using the WireTests framework. After running tests, we find items to fix either in the API.md or the core. Then I do a round of proofreading and edits. Finally, both the class API.md file and the tests are committed to the core. At this point, most of the major classes in ProcessWire have their own API.md documentation files and tests, so now we're focused on some of the more specific tools and classes. I also wanted to mention that the Modules class got some major CLI improvements. Here's the full CLI command set available for the $modules API now: Modules ======= php index.php modules list [site|core] List installed modules, optionally limited to site or core modules php index.php modules unlist [site|core] List uninstalled modules, optionally limited to site or core modules php index.php modules info <name> [property] Get JSON of all info for module or optionally info property php index.php modules install <name> Install module php index.php modules uninstall <name> Uninstall module php index.php modules exists <name> Does given class name resolve to a module? (Yes/No) php index.php modules installed <name> Is module installed? (Yes/No) php index.php modules config <name> Get configuration data for module as JSON php index.php modules config <name> <property> Get value for property in module config php index.php modules dir <name> Query ProcessWire modules directory for module info php index.php modules updates [name] List available updates for installed site modules, or check one module php index.php modules download <name> [--install] Download module from PW modules directory (+ optionally install) php index.php modules download <url> [--install] Download module ZIP file from https URL (+ optionally install) php index.php modules update <name> [--force] Download and apply an available module update php index.php modules delete <name> Delete/erase uninstalled module from file system Optionally append --json to any of the above commands for more verbose JSON output While I'm posting CLI commands, here's the full command set for the updated WireApiDocs class: WireApiDocs =========== php index.php docs list List classes with API.md docs php index.php docs list 'Class*' List classes matches wildcard pattern php index.php docs list-verbose List classes with API.md docs in verbose mode php index.php docs list-verbose 'Class*' List classes matching pattern in verbose mode php index.php docs get <class> Get API docs for given class php index.php docs toc <class> Get table of contents for given class php index.php docs chapter <class> <num> Get body for given class and chapter number php index.php docs chapter <class> 'Title' Get body for given class and chapter title php index.php docs methods <class> Get public methods for given class (* prefix = hookable) php index.php docs method <class> <method> Get details for a single method (JSON only) php index.php docs classinfo <class> Get class info: parent, interfaces, traits php index.php docs constants <class> Get public constants for a class php index.php docs properties <class> Get @property annotations for a class php index.php docs groups <class> Get #pw-summary-[group] descriptions for a class php index.php docs vars List all API variables and the classes they represent WireApiDocs commands return JSON by default. To make command return plain text (not JSON), append `-text` to the command name, i.e. `list-text` See the dev branch commit log for additional core updates this week: https://github.com/processwire/processwire/commits/dev/. If using AgentTools, grab this week's new version too. More next week. Thanks for reading and have a great weekend!
    1 point
  40. FYI - latest commit fixes that bug.
    1 point
  41. Hi @gebeer - great write-up! RockPageBuilder already has a built-in show key in each block’s info(): 'show' => 'template=project', // selector string // or 'show' => fn($page) => $page->template->name === 'project', That filters the add-menu via getAddableBlocks(). For a handful of blocks with simple rules, it’s the quickest path — no hook, no template metadata. Your rpb_blocks_allowed + getAllowedBlocks hook is better when: the same RPB field sits on multiple templates with different palettes you want the allow-list in the template migration (one place), not scattered across block files you need enforcement at getAllowedBlocks level — show is UI-only; API/programmatic creation goes through isAllowed() and ignores show So: show = per-block, UI convenience. Your hook = per-template, centralized, actually enforced. Also worth noting: RPB already scopes by field folder (/site/templates/RockPageBuilder/{fieldname}/) — that’s a third axis, useful when different fields need different palettes regardless of template. Ask your AI if you want to know more. Thanks for documenting the hook pattern — it fills a real gap show doesn’t cover.
    1 point
  42. You can send one that you do need to me. My niece is coming this summer too, just post it to her address first please :D
    1 point
  43. Enables AI coding agents to access ProcessWire’s API. Also provides a content migration system. This module provides a way for Claude Code (or other AI helpers) to have full access to the ProcessWire API via a command-line interface (CLI). Once connected to your site, you can ask Claude to create and modify pages, templates and fields, or do anything that can be done with the ProcessWire API. It's even possible for an entire site to be managed by Claude without the need for ProcessWire's admin control panel, though we're not suggesting that just yet. While working with Claude Code, I asked what would be helpful for them in working with ProcessWire, and this module is the result. Claude needed a way to quickly access the ProcessWire API from the command line, and this module provides 3 distinct ways for Claude to do so. Claude collaborated with me on the development of the AgentTools module, and the accompanying ProcessAgentTools module was developed entirely by Claude Code. Admittedly, a big part of the purpose of this module is also to help me learn AI-assisted development, as I'm still quite new to it, but learning quickly. This module aims to add several agent tools over time, but this first version is also somewhat of a proof of concept. Its first feature is basic migrations system, described further in this document. Please note that this module should be considered very much in 'beta test' at this stage. If you do use it in production (such as the migrations feature) always test locally and have backups of everything that can be restored easily. While I've not run into any cases where I had to restore anything, just the nature of the module means that you should use extra caution. Continue reading in the GitHub README Agent Tools in the modules directory
    1 point
  44. Hi everyone, Needed a way to embed polls and quizzes directly into page content — shortcode in any text field, renders as a cache-safe interactive widget. Built it, it works well, sharing it. GitHub: https://github.com/mxmsmnv/Pulse Screenshot: What it does Polls and quizzes embedded via shortcode into any text field: [[pulse:poll name="my-poll"]] [[pulse:quiz name="my-quiz"]] Polls — voting with live results, multi-select, allow-other option, duplicate protection (cookie+IP, user session, or soft). Quizzes — three modes: graded — points, pass/fail threshold, answer review personality — options award points to outcomes, winning outcome shown at end exam — graded plus timer, attempt limit, question bank, certificate Visual questions — question-level images and image-option layouts. Admin workspace — Setup → Pulse with full CRUD, analytics, CSV/JSON export, import, clone, and demo installer. Security: All scoring server-side — is_correct / outcome_points never reach the client before submission CSRF mandatory on all submissions (token from /pulse/state) Honeypot + rate limiting by hashed IP Voter cookies and IPs stored as salted hashes only Exam HMAC-signed question sets, server-enforced timeouts, signed certificates Cache-safe: renders a static shell, hydrates via JS — works with ProCache. Requirements: ProcessWire 3.0+, PHP 8.2+ MIT License.
    1 point
  45. My workplace at the moment 😊
    1 point
  46. Since back in 1996 I'm a big fan and user of the smallest Cherry Keyboards, with and without NumPads. But mainly the types without NumPads, CHERRY G84-4100: But on my primary Desktop working place I use a Razer Huntsman Elite RZ03-0187 :
    1 point
  47. I've been meaning to revise PageimageSrcset for a while now, to remove some features that I felt were unnecessary and to implement a better rendering strategy. The result is PageimageSource. What does it do? It provides a configurable srcset method/property for Pageimage It allows WebP to be enabled for images it generates. It allows Pageimage:render() to return a <picture> element It provides a Textformatter that replaces <img> elements with the output of Pageimage:render() Although it is based on a current module, this should still be considered beta and not used in production without a prior development stage. Here's the README: PageimageSource Extends Pageimage with a srcset property/method plus additional rendering options. Overview The main purpose of this module is to make srcset implementation as simple as possible in your template code. For an introduction to srcset, please read this Mozilla article about responsive images. Installation Download the zip file at Github or clone the repo into your site/modules directory. If you downloaded the zip file, extract it in your sites/modules directory. In your admin, go to Modules > Refresh, then Modules > New, then click on the Install button for this module. ProcessWire >= 3.0.165 and PHP >= 7.3 are required to use this module. Configuration To configure this module, go to Modules > Configure > PageimageSource. Default Set Rules These are the default set rules that will be used when none are specified, e.g. when calling the property: $image->srcset. Each set rule should be entered on a new line, in the format {width}x{height} {inherentwidth}w|{resolution}x. Not all arguments are required - you will probably find that specifying the width is sufficient for most cases. Here's a few examples of valid set rules and the sets they generate: Set Rule Set Generated Arguments Used 320 image.320x0-srcset.jpg 320w {width} 480x540 image.480x540-srcset.jpg 480w {width}x{height} 640x480 768w image.640x480-srcset.jpg 768w {width}x{height} {inherentwidth}w 2048 2x image.2048x0-srcset.jpg 2x {width} {resolution}x How you configure your rules is dependent on the needs of the site you are developing; there are no prescriptive rules that will meet the needs of most situations. This article gives a good overview of some of the things to consider. When you save your rules, a preview of the sets generated and an equivalent method call will be displayed to the right. Invalid rules will not be used, and you will be notified of this. WebP If enabled, WebP versions of the image and srcset variations will be generated and these will be returned by Pageimage::srcset(). As with the default implementation, the image with the smaller file size is returned. In most cases this is the WebP version, but sometimes can be the source. Make sure to experiment with the quality setting to find a value you find suitable. The default value of 90 is fine, but it is possible that lower values will give you excellent kB savings with little change in overall quality. For more information on WebP implementation please read the blog posts on the ProcessWire website. Rendering These settings control how the output of Pageimage::render() is modified. Use Lazy Loading? When enabled this adds loading="lazy" to the <img> attributes. It is useful to have this on by default, and you can always override it in the options for a specific image. Use the <picture> element? When enabled, the <img> element is wrapped in a <picture> element and <source> elements for original and WebP variations are provided. This requires WebP to be enabled. For more information on what this does, have a look at the examples in Pageimage::render() below. Remove Variations If checked, the image variations generated by this module are cleared on Submit. On large sites, this may take a while. It makes sense to run this after you have made changes to the set rules. Please note that although the module will generate WebP versions of all images if enabled, it will only remove the variations with the 'srcset' suffix. Usage Pageimage::srcset() // The property, which uses the set rules in the module configuration $srcset = $image->srcset; // A method call, using a set rules string // Delimiting with a newline (\n) would also work, but not as readable $srcset = $image->srcset('320, 480, 640x480 768w, 1240, 2048 2x'); // The same as above but using an indexed/sequential array $srcset = $image->srcset([ '320', '480', '640x480 768w', '1240', '2048 2x', ]); // The same as above but using an associative array // No rule checking is performed $srcset = $image->srcset([ '320w' => [320], '480w' => [480], '768w' => [640, 480], '1240w' => [1240], '2x' => [2048], ]); // The set rules above are a demonstration, not a recommendation! Image variations are only created for set rules which require a smaller image than the Pageimage itself. This may still result in a lot of images being generated. If you have limited storage, please use this module wisely. Pageimage::render() This module extends the options available to this method with: srcset: When the module is installed, this will always be added, unless set to false. Any values in the formats described above can be passed. sizes: If no sizes are specified, a default of 100vw is assumed. lazy: Pass true to add loading=lazy, otherwise false to disable if enabled in the module configuration. picture: Pass true to use the <picture> element, otherwise false to disable if enabled in the module configuration. Please refer to the API Reference for more information about this method. // Render an image using the default set rules // WebP and lazy loading are enabled, and example output is given for <picture> disabled and enabled echo $image->render(); // <img src='image.webp' alt='' srcset='image.jpg...' sizes='100vw' loading='lazy'> /* <picture> <source srcset="image.webp..." sizes="100vw" type="image/webp"> <source srcset="image.jpg..." sizes="100vw" type="image/jpeg"> <img src="image.jpg" alt="" loading="lazy"> </picture> */ // Render an image using custom set rules echo $image->render(['srcset' => '480, 1240x640']); // <img src='image.webp' alt='' srcset='image.480x0-srcset.webp 480w, image.1240x640-srcset.webp 1240w' sizes='100vw' loading='lazy'> /* <picture> <source srcset="image.480x0-srcset.webp 480w, image.1240x640-srcset.webp 1240w" sizes="100vw" type="image/webp"> <source srcset="image.480x0-srcset.jpg 480w, image.1240x640-srcset.jpg 1240w" sizes="100vw" type="image/jpeg"> <img src="image.jpg" alt="" loading="lazy"> </picture> */ // Render an image using custom set rules and sizes // Also use the `markup` argument // Also disable lazy loading // In this example the original jpg is smaller than the webp version echo $image->render('<img class="image" src="{url}" alt="Image">', [ 'srcset' => '480, 1240', 'sizes' => '(min-width: 1240px) 50vw', 'lazy' => false, ]); // <img class='image' src='image.jpg' alt='Image' srcset='image.480x0-srcset.webp 480w, image.1240x0-srcset.webp 1240w' sizes='(min-width: 1240px) 50vw'> /* <picture> <source srcset="image.480x0-srcset.webp 480w, image.1240x0-srcset.webp 1240w" sizes="(min-width: 1240px) 50vw" type="image/webp"> <source srcset="image.480x0-srcset.jpg 480w, image.1240x0-srcset.jpg 1240w" sizes="(min-width: 1240px) 50vw" type="image/jpeg"> <img class='image' src='image.jpg' alt='Image'> </picture> */ // Render an image using custom set rules and sizes // These rules will render 'portrait' versions of the image for tablet and mobile // Note the advanced use of the `srcset` option passing both `rules` and image `options` // WebP is disabled // Picture is disabled echo $image->render([ 'srcset' => [ 'rules' => '320x569, 640x1138, 768x1365, 1024, 1366, 1600, 1920', 'options' => [ 'upscaling' => true, 'hidpi' => true, ], ], 'sizes' => '(orientation: portrait) and (max-width: 640px) 50vw', 'picture' => false, ]); // <img src='image.jpg' alt='' srcset='image.320x569-srcset-hidpi.jpg 320w, image.640x1138-srcset-hidpi.jpg 640w, image.768x1365-srcset-hidpi.jpg 768w, image.1024x0-srcset-hidpi.jpg 1024w, image.1366x0-srcset-hidpi.jpg 1366w, image.1600x0-srcset-hidpi.jpg 1600w, image.jpg 1920w' sizes='(orientation: portrait) and (max-width: 768px) 50vw' loading="lazy"> TextformatterPageimageSource Bundled with this module is a Textformatter largely based on TextformatterWebpImages by Ryan Cramer. When applied to a field, it searches for <img> elements and replaces them with the default output of Pageimage::render() for each image/image variation. Assuming a default set of 480, 960 and lazy loading enabled, here are some examples of what would be returned: Example <figure class="align_right hidpi"> <a href="/site/assets/files/1/example.jpg"> <img alt="" src="/site/assets/files/1/example.300x0-is-hidpi.jpg" width="300" /> </a> </figure> WebP enabled <figure class="align_right hidpi"> <a href="/site/assets/files/1/example.jpg"> <img alt="" src="/site/assets/files/1/example.300x0-is-hidpi.webp" width="300" srcset="/site/assets/files/1/example.300x0-is-hidpi.webp 480w" sizes="100vw" loading="lazy" /> </a> </figure> <picture> enabled <figure class="align_right hidpi"> <a href="/site/assets/files/1/example.jpg"> <picture> <source srcset="/site/assets/files/1/example.300x0-is-hidpi.webp 480w" sizes="100vw" type="image/webp"> <source srcset="/site/assets/files/1/example.300x0-is-hidpi.jpg 480w" sizes="100vw" type="image/jpeg"> <img alt="" src="/site/assets/files/1/example.300x0-is-hidpi.jpg" width="300" loading="lazy" /> </picture> </a> </figure> Because the variation is small - 300px wide - the srcset only returns the source image variation at the lowest set width (480w). If the source image was > 1000px wide, there would be a variation at both 480w and 960w. PageimageSrcset This module is built upon work done for PageimageSrcset, which can be considered a first iteration of this module, and is now deprecated. Migration PageimageSource is a simplified version of PageimageSrcset with a different approach to rendering. Most of the features of the old module have been removed. If you were just using $image->srcset(), migration should be possible, as this functionality is essentially the same albeit with some improvements to image variation generation.
    1 point
  48. Thanks for the kind words! I have a month's worth of modules, not as big as Collections, Ichiban, or Context, but very useful. Usually, when I run into a problem, I try to solve it right away using a module so that other users can use it in the future.
    1 point
×
×
  • Create New...