Leaderboard
Popular Content
Showing content with the highest reputation on 06/08/2026 in Posts
-
Thx for the loveletter @gebeer and others. I thought I've already replied, but it seems that post got lost. I'm getting a lot of 500 errors these days in the forum. I wouldn't say I've quit the community. What I've stepped away from is making significant investments in the ecosystem and trying to build a business around it. That didn't work out for me, so I had to move on. As for RockMigrations: I understand and even share some of the concerns raised here (even though I find terms like "bloated nature" a bit harsh). It started as a somewhat experimental proof of concept, and yes, I built it with my other modules in mind. At the same time, it has always been completely free because I felt it was too important to put behind a paywall, and it has always been open to PRs. 😉 Nevertheless, over time it turned out to be very reliable and became an essential tool for my work. Considering that all my ProcessWire projects from the last decade rely on it, I expect it will remain supported for quite some time. That's the status quo. What I did find a little surprising, though, was seeing migrations become part of the core years later, seemingly almost overnight, while RockMigrations and the other migration modules weren't much of a reference point in that process. Unfortunately, it's not the first time I've seen that happen. What I learned from that experience is that it's not something I can build a business on. So I really haven't quit on the community — I've simply moved on from trying to build a business around my ProcessWire contributions, and my reduced forum activity is just a consequence of that. But I check in from time to time to see what's going on and I try my best to be available and helpful if anybody needs anything related to my modules. 🙂5 points
-
I’ve been doing regular ProcessWire updates for years, and honestly, they’re usually pretty painless. Ryan keeps things sane, modules mostly behave, and if you don’t wait forever between updates, compatibility drama is rare. But there’s still one part that always felt a bit… clicky. Check module updates. Download paid modules ZIP files. Upload/install. Refresh modules. Commit. Repeat. Then core. Then smoke test. Not hard, just enough tiny steps to make you think: “surely my robot coworker can do this?” So I made a reusable AI-agent skill for doing ProcessWire system updates through DDEV CLI: https://github.com/gebeer/processwire-ai-docs/tree/main/skills/processwire-system-update-cli plays nice with https://github.com/gebeer/processwire-ai-docs/tree/main/skills/processwire-ddev-cli Don't have ddev? Too bad, consider using it or tweak the skill. Or use Ryan's AgentTools module. Your agent will figure it out, eventually. What it does The workflow is basically: Ask ProcessWire what’s outdated via ProcessWireUpgradeCheck Check module requirements before touching anything Update modules first, core second, unless compatibility says otherwise Install public and Pro module ZIPs from the CLI Refresh module caches and verify versions Commit every module update separately Update ProcessWire core last Smoke test the site in a browser (given your agent has the tooling. I use cdp-cli with a skill derived from its readme). Less admin panel dance, more deterministic “do the thing, verify the thing, commit the thing”. The important bit: compatibility first The skill does not blindly follow “modules first” in all cases. Before updating, it checks module requirements from places like: public static function getModuleInfo() { return [ 'requires' => [ 'ProcessWire>=3.0.240', 'PHP>=8.1', ], ]; } …and from the module directory data returned by ProcessWireUpgradeCheck. If a module needs a newer PHP version, the agent should stop and warn you. If a module needs a newer ProcessWire version, that’s a legit exception to the usual “modules before core” rule: update core first, then come back to modules. This matters especially for folks who wait a long time between updates. If you update regularly, you may never hit this. If you update once every few years, dependency gremlins are much more likely. Pro modules too For Pro modules, the skill doesn’t pretend it can magically access your PW account. It scans first, sees which Pro modules need updates, then asks you for local ZIP paths. After that it copies the ZIP into the project cache and uses ProcessWire’s own module installer internals: ProcessModuleInstall::unzipModule() modules()->refresh() modules()->resetCache() Tiny gotcha: unzipModule() deletes the ZIP it extracts, so the skill uses a temp copy. Ask me how I know. 😄 Why I like it The end result is not fancy. That’s the point. It’s just a solid update ritual encoded as a skill: scan first check compatibility snapshot DB update one module verify commit repeat update core browser smoke test For my latest run it took care of TracyDebugger, MaintenanceMode, ProFields Table, ProFields RepeaterMatrix, ProMailer and ProcessWire dev core with clean commits for each step. ProcessWire updates were already pretty friendly. This just removes the boring click choreography. Coffee stays warm. Git history stays clean. Robots get to do robot work 🤖5 points
-
Great :-) I have also done a small genealogy/history project with ProcessWire this year: https://www.glashytt.at/3 points
-
Hi everyone, Most project management tools are generic. Verk is built specifically around ProcessWire's data model — tasks link directly to PW pages, the calendar reads real page date fields, and content audits run PW selectors. Everything stays inside your install. GitHub: https://github.com/mxmsmnv/Verk Why Verk? Verk means "work" or "task" in Icelandic and Swedish. Short, abstract, and fitting for a tool built around getting things done inside ProcessWire. It follows the same naming approach as other modules in this series — Arbor, Ichiban, Collections — names that mean something without being literal. Screenshots: What it does Dashboard — open tasks, upcoming publications, audit alerts, and active sprint planning Tasks — create/assign tasks linked to specific PW pages; one click opens the page editor directly Calendar — month, week, and quarter views for page publications and task due dates Content Audit — run PW selectors with dot-notation field checks to find missing content Knowledge Base — rich editorial notes organized by category, searchable and exportable Sprints — sprint planning, quarter grouping, task assignment, DOCX export, and progress tracking Key details: Tasks store page_id — page data lives in PW, never duplicated Page Editor Widget injected via hookAfter('ProcessPageEdit::buildForm') — no template files modified Audit to tasks — bulk-create tasks from audit results with page context prefilled Rich text via TinyMCE when InputfieldTinyMCE is installed DOCX exports for task lists, notes, sprints, and knowledge base Return-aware forms — create/edit flows preserve filtered list URLs Requirements: ProcessWire 3.0.200+, PHP 8.0+ MIT License.2 points
-
Hi @maximus - I have a fairly detailed hook set up for SEOMaestro. It tweaks the homepage title, but most importantly it sets an automatic description for staff bio pages amd blog posts from existing text fields. It also pulls the first image from the blog post for the ogimage. If I switch to Ichiban I think I will need to do something similar so that staff don't need to manually enter separate descriptions for these pages. Is there an available hook to replicate this? And, if so, could the dashboard process this hook so it knows that these pages actually do have completed descriptions. $this->wire()->addHookAfter('SeoMaestro::renderSeoDataValue', function (HookEvent $event) { $group = $event->arguments(0); $name = $event->arguments(1); $value = $event->arguments(2); $p = $event->wire('page'); if($p->template->name == 'admin' && $event->wire('process') == 'ProcessPageEdit' && $event->wire('input')->get('id')) { $p = $event->wire('pages')->get((int) $event->wire('input')->get('id')); } $service_name = $event->wire('siteSettings')->serviceName ?? 'My Site Title'; if($group === 'meta' && $name === 'title') { if($p->id === 1) { // remove automatically appended [[service_name]] from homepage because we add it to the front in the SEO tab of the homepage $event->return = str_replace(' | [[service_name]]', '', $value); } else { $event->return = str_replace('[[service_name]]', $service_name, $value); } } // people (staff & experts), blog posts — keep the meta description to whole words under 155 chars, // using the editor's explicit description when set, otherwise falling back to summary|body. if(($p->template->name === 'person' || $p->template->name === 'blog-post') && $group === 'meta' && $name === 'description') { $source = $value !== '' ? $value : $this->wire('sanitizer')->textarea($p->get('summary|body')); $event->return = $this->wire('sanitizer')->truncate($source, 155); } elseif($p->id !== 1 && $group === 'meta' && $name === 'description' && $value == '') { $event->return = $this->wire('pages')->get(1)->seo_fields->meta_description; } if($p->image && $value !== "" && $group === 'opengraph' && $name === 'image') { $event->return = $p->image->httpUrl; } elseif($p->template == 'blog-post' && $p->images->count() > 0 && $value !== "" && $group === 'opengraph' && $name === 'image') { $event->return = $p->images->first->httpUrl; } });2 points
-
Hi all — we're putting this one up as a public beta and looking for feedback before we tag a stable release. How it started. Over the past months we've been moving an old blog into a fresh PW site using our own SiteSync module and a Claude Code agent doing most of the migration grunt work. At some point the blog owner mentioned, in that very offhand way clients do, "hey, an image search would be nice." It was Saturday afternoon, so we let the agent build a prototype, pushed it through SiteSync, tested it on the phone an hour later. Worked great. Search results were… not great. But the search wasn't the problem – the underlying data was. Thousands of imported images, almost no descriptions, no tags, no nothing. So we needed a way to retroactively caption and tag a few thousand images without clicking through hundreds of page edits one by one. Since PW (rightly) attaches images to the pages they belong to, we needed a tool that reaches across the whole install at once and – crucially – can edit metadata in bulk. Why not the existing modules? We looked at the two obvious candidates: Media Manager by @kongondo – great if you're starting fresh and want a central media hub. But it's its own storage layer: you upload INTO Media Manager, editors pick FROM Media Manager. Images already sitting on per-page image fields stay invisible to it. Also commercial. MediaLibrary by @BitPoet – adds a MediaLibrary template with its own MediaImages / MediaFiles fields plus a CKEditor picker. Same pattern: a separate page hierarchy you migrate media into. Both are well-designed for "we want a central media model from day one." Neither helps you when the media is already scattered across lead_image, body_images, gallery, images_in_some_repeater etc. Migrating that into a different storage layer would have broken the original page model the blog depends on. So we built Image Library: a Process module that does nothing to your data – it just surfaces a cross-site table view of everything that's already there, with serious bulk editing on top. The bulk-edit part – the reason this module exists. Selection as a paintbrush. You tick N rows across any pages, templates and image fields. Then you edit a cell on ANY of those rows — the popup gains an Add / Replace mode picker (tags additionally offer Remove) and the value gets broadcast to the entire selection in one server round. Same row applies to description, tags, every custom subfield, AND the filename (with placeholders: (n), (n2)..(n5) padded counters, (N) total, (t) page title, (d) date, (p) page name, (f) field name → e.g. rename 200 selected files to event-2025-(n3).jpg). Same row applies to delete (one trash click, whole selection gone behind one confirm dialog with a where-used preflight – see below). Edits that push a row OUT of the active filter ("missing tags" → tag assigned → row no longer matches) fade out and drop from the table; counters auto-decrement. Other highlights: One sortable, paginated, bookmarkable table across every FieldtypeImage field on every page on every template (with config-side blacklists). Inline edit per cell – multilang-aware: language tabs in the popup, all languages committed in one save. Typed widgets per custom subfield: checkbox, date, integer, options (single + multi), and FieldtypePage rendered through PW's actually configured Inputfield (PageAutocomplete / PageListSelect / ASMSelect / whatever the field uses) — no re-implementation. Replace image in place (drag-drop or upload icon) – basename stays, variations regen. Renaming an image in the library instantly rewrites every CKEditor/TinyMCE embed of that file across the site — original and all variations, in every language — so links never break, and a summary dialog shows which pages were updated. Delete with where-used preflight: dialog scans every Textarea via $pages->findIDs("field%='/pid/stem.', include=all") and lists the pages where the image is still embedded in rich text – CKEditor + TinyMCE both, multilang-aware, with direct edit links so you can fix embeds before deleting. JSON / CSV export + import for offline metadata work – hand a CSV to a copywriter or feed it to your agent, get it back, import it. View prefs (columns, page size, bookmarks) live in $user->meta, cross-device. Status. v0.54.x – public beta. Module + docs (EN + DE concept) at GitHub or the Modules Directory Feedback welcome – especially edge cases we haven't seen yet (weird Fieldtype combos in custom-field templates, ProFields, Repeaters / RepeaterMatrix nesting). And if you've got a use case the current feature set doesn't cover, let us know. Cheers, Mike1 point
-
I'll take a look in the near future, I think it's possible to automate this somehow.1 point
-
1 point
-
So... to keep up with your awesome modules, I decided to up my caffeine-intake to 1,200mg per day now. I love it! 🤯1 point
-
Hi Krlos, Thanks for confirming, and good catch on the admin preview. The frontend output was already resolving the Combo image correctly, but the page editor preview JavaScript was still only recognizing simple tokens like {image} and field:image. It did not recognize dotted expressions such as {combo.image} or combo.image when deciding whether to use the resolved URL for the preview. I’ve fixed this in v0.1.2-alpha. After updating, the resolved image path and the social preview should now appear in the editor for Combo image sources as well.1 point
-
Yes, I see a lot of issues there, of course I'll fix them! Thanks a lot for testing!1 point
-
@maximus - this is really great - thank you. I have gone to town with bug reports and feature suggestions on the repo though - hope you don't mind the barrage :)1 point
-
That’s brilliant 🤩 Thanks for the skill1 point
-
Hi everyone, I've been building this for a while - a full genealogy system inside ProcessWire. Family trees, people, relationships, sources, documents, DNA kits, research workflow, and GEDCOM export. All inside the PW admin. GitHub: https://github.com/mxmsmnv/Arbor Status: Beta. Usable on a test copy. Always backup before installing. Screenshots: Why ProcessWire for genealogy? Genealogy data is complex, relational, and research-driven - not a blog. ProcessWire's flexible data model and custom DB table support make it a natural fit. Everything in Arbor lives in arbor_ prefixed tables, completely separate from the PW page tree. What it does Multiple trees - owner/public settings per tree Person profiles - names, events, notes, sources, photos, relationships Family/union management - partners, parents, children, relationship types Interactive tree viewer - main person panel, selected-person panel, agenda, legend Places & repositories - archives, sources, citations, documents, document leads Research workflow - questions, tasks, search log, proof conclusions, next actions DNA - kits, matches, segments GEDCOM 5.5.1 and GEDCOM 7 export GEDCOM import foundation (in progress) AI helper via AiWire-compatible providers - research suggestions, name analysis REST API via ArborApi submodule Three submodules: Arbor - schema, models, configuration, permissions, shared services ProcessArbor - admin UI under Setup → Arbor ArborApi - optional REST endpoints Requirements: ProcessWire 3.0.200+, PHP 8.1+, MySQL/MariaDB with InnoDB MIT License.1 point
-
Hi everyone, I've been running this module in production a spirits catalog with 12,000+ products — for several months. Today I'm releasing it publicly. GitHub: https://github.com/mxmsmnv/Collections The problem ProcessWire's page tree is brilliant for site structure. It's painful for data management. When you have thousands of pages as records — products, listings, vacancies, menu items — you hit the same walls on every project: no table view, no inline filters, no bulk actions, no export, no REST API, no role scoping per dataset. Every PW developer has solved some version of this. Collections solves it once. Screenshots What it does Gives any ProcessWire template a configurable admin table — live search, dropdown filters, inline status toggles, bulk actions, CSV/JSON export, and a REST API — all configured through a UI, without writing code. Admin UI: Configurable columns per collection with custom labels Live search with 300ms debounce across multiple fields including Page references Dropdown filters for FieldtypePage and FieldtypeOptions fields Inline publish/unpublish toggle via AJAX Bulk actions: publish, unpublish, delete with CSRF protection CSV and JSON export with active filters preserved Role-based permissions matrix — scope each role per collection "View in Collection" button injected into the page edit form REST API: Bearer token, query param, HTTP Basic, and PW session auth API key management with expiration dates and per-key capability scopes SHA-256 hashed keys, usage tracking, rate limiting (100 req/min) WireCache support for GET responses ProFields support: Table, Textareas, Multiplier, Repeater Matrix, Combo — including dot-notation for subfields (address.city, blocks.hero.title, prices.*.amount) Field types: Text, Textarea, Integer, Float, Checkbox, URL, Email, Date, Image, File, FieldtypeFileB2, FieldtypePage, FieldtypeOptions, MapMarker, Color Requirements: ProcessWire 3.0.244+, PHP 8.2+ There's a thread from 2013 asking for exactly this: Module Idea: Flat Listings — here it is, 12 years later. Known issues are tracked on GitHub — the module is stable for production use, active development continues.1 point
-
Core updates A new WireApiDocs class was added that provides an API... for APIs. It’s a tool that can parse ProcessWire’s API.md files to provide various methods for finding and pulling documentation. It also includes the ability to get certain parts of an API.md (chapters). This new tool is accessible through $wire->docs, which returns an instance of WireApiDocs. Here’s a few usage examples: $api = $wire->docs; $api->get(); // get summary array of all documented classes $api->get('Pages'); // get docs for Pages class $api->get('Fieldtype*'); // get names of all Fieldtype classes Lots more examples here: https://processwire.com/api/ref/wire-api-docs/get/ and the entire class reference can be found here: https://processwire.com/api/ref/wire-api-docs/ WireApiDocs also comes with a full CLI command set, which can be viewed by typing: php index.php docs WireApiDocs: ============ php index.php docs list List classes with API docs as string php index.php docs list 'Class*' List classes matching wildcard pattern as string php index.php docs list-json List classes with API docs in JSON php index.php docs list-json 'Class*' List classes matches wildcard pattern in JSON php index.php docs list-json-verbose List classes with API docs in JSON verbose mode php index.php docs list-json-verbose 'Class*' List classes matching pattern in verbose JSON php index.php docs get Class Get API docs for given Class php index.php docs get-json Class Get JSON API docs for given Class php index.php docs toc Class Get table of contents for given Class (string) php index.php docs toc-json Class Get table of contents for given Class (json) php index.php docs body Class num Get body for given Class and chapter number php index.php docs body Class 'title' Get body for given Class and chapter title New API.md files Speaking of API docs, several new API.md files were added to the core this week. You can view any of them by clicking the links below: WireArray: Covers the base collection class for all PW iterable sets. WireData: Covers the base data-storage class used throughout ProcessWire. LanguageSupport: Covers all things multi-language in ProcessWire. This is probably our most comprehensive API.md yet. WireHooks: Comprehensive guide to ProcessWire's entire hooks system. Fields: the API variable that manages all custom fields in ProcessWire. Templates: The API variable that manages all Template instances. FieldtypeOptions: Field that stores one or more selected options from a predefined list. New LanguagePorter class for exporting and importing translations This new class provides a simple "export CSV" and "import CSV" for language static translations. It was added so that agents and developers could have an easy way to pull all text to translate, translate it, then push it back into the system. It is used by the new "static phrase translation" task that appears in this week's new version of AgentTools. The LanguagePorter can be accessed for any language from the $language->porter() method. WireTests in the core Tests for the WireTests module are now being placed directly in the core. We are slowly migrating the existing tests, while new tests are being committed to the core rather than in the WireTests module. This week tests were added for the following (click links to view tests file): Sanitizer, WireData, WireArray, WireDateTime, LanguageSupport (covers all multi-language features). AgentTools updates New “run in background” option for Site Engineer and Page Engineer AgentTools now has the ability to queue and run AI agent requests in the background on the server, rather than through a web request. This is especially helpful with long running tasks, as they can run without Apache/server http timeouts. The AgentTools module configuration screen tells you what you need to do to enable background jobs. But primarily it’s just a matter of enabling a cron job for AgentTools. When the background job is finished, you can view the agent’s response in the admin. But it also gets emailed to you. Background jobs are available for Site Engineer, Page Engineer as well as the built-in and custom tasks. New built-in task: Static phrase translation and language pack creation Per last week’s update, AgentTools now comes with several built-in AI tasks that you can use. Added this week is yet another new task for multi-language sites: you can now have all the phrases in your site, in modules, or even the entire core, translated to another language by your AI agents. Not only does the task handle all of the translation, but it also handles creating and installing the language pack(s) once it is finished. Please note that this particular task requires that you 1) have ProcessWire 3.0.264 or newer; and 2) have multi-language support enabled on your installation. Also note that mass translation of phrases can take some time, so the new background mode can come in especially handy when doing lots of automatic translations. New engineer preview / dry-run mode If you want to know what the agent would do to accomplish something, without actually committing the changes now, check the new “Preview” checkbox before submitting an Engineer request. The agent will run in a read-only mode to describe what it would do before you commit to making it do the real thing.1 point
-
This week I've been doing a major overhaul of the /wire/core/ directory structure aimed at improving and adding documentation. Now all core classes that will receive their own API.md documentation also have their own directory. The /wire/core/ directory kind of resembles the /wire/modules/ structure now. In addition, new API.md files have been created for the Pages, Page, PageArray, Modules and Module, all of which also improve the online API reference documentation too, which is what those links are linking to. We'll continue adding more API.md documents every week. Every time a new API.md file is completed, it gets sent over to the WireTests module to verify that everything documented in the API.md works exactly as stated. So new tests have been committed to that module as well, and more will be getting added every week. In addition, ProcessWire now has a CLI (command line interface) installer. Installing ProcessWire is as simple as typing this from the command line: php install.php When you do that, it'll present you with the installation options (see below). For human users, the "Standard usage" option is likely to be best, while AI agents will likely prefer the "Alternate usage" option: Standard usage: php install.php --generate Generate ./install-config.php for you to edit php install.php --config install-config.php Install from settings in ./install-config.php Alternate usage: echo '{"dbName":"mydb",...}' | php install.php Install from settings in JSON string php install.php --json '{"dbName":"mydb",...}' Install using an inline JSON string Other: php install.php --help Display all options That last option "--help" displays a giant screen of options, so I won't repeat it here, but take a look if you are interested. New versions of FieldtypeTable, FieldtypeCustom, FieldtypeCombo and FieldtypeRepeaterMatrix next week. Lots more in progress here too so stay tuned! Thanks for reading and have a great weekend!1 point
-
1 point